package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"io"
	"net/http"
	"os"
	"sort"
	"strings"

	"log"

	"github.com/utkarsh-1905/thapar-time-table/utils"
)

func init() {
	fmt.Println("Initializing server...")
	// UNCOMMENT THIS TO RE-GENERATE THE TIMETABLE
	// BE CAUTIOUS WHEN USING THIS
	// utils.GetSubjectMapping()
	// utils.GenerateJson()
	fmt.Println("Server initialized")
}

func main() {

	dataFile, _ := os.Open("./data.json")
	data := make(map[string]map[string][][]utils.Data)
	byteRes, _ := io.ReadAll(dataFile)
	json.Unmarshal([]byte(byteRes), &data)
	defer dataFile.Close()
	table, _ := template.ParseFiles("./templates/table.html")
	home, _ := template.ParseFiles("./templates/home.html")
	courseNameCode, _ := template.ParseFiles("./templates/course-name-code.html")
	errorPage, _ := template.ParseFiles("./templates/error.html")

	type HomeData struct {
		Sheets  []string
		Classes map[string][]string
	}

	var sheets []string
	for i := range data {
		sheets = append(sheets, strings.Trim(i, " "))
	}
	sort.StringSlice(sheets).Sort()
	classes := make(map[string][]string)
	for i, d := range data {
		temp := make([]string, 0)
		for j := range d {
			temp = append(temp, strings.Trim(j, " "))
		}
		sort.StringSlice(temp).Sort()
		classes[i] = temp
	}
	h := HomeData{
		Sheets:  sheets,
		Classes: classes,
	}

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != "/" {
			errorPage.Execute(w, "This page is under construction !!(404)")
			return
		}
		err := home.Execute(w, h)
		if err != nil {
			log.Printf("Error while executing home template: %v", err)
		}
	})

	type TimeTableData struct {
		Data      [][]utils.Data
		ClassName string
	}

	http.HandleFunc("/timetable", func(w http.ResponseWriter, r *http.Request) {
		class := r.URL.Query().Get("classname")
		sheet := r.URL.Query().Get("sheet")

		flag := true
		for _, d := range classes[sheet] {
			if class == d {
				flag = false
			}
		}
		if flag {
			errorPage.Execute(w, "Invalid category/class combination")
			return
		}
		data := TimeTableData{
			Data:      data[sheet][class],
			ClassName: class,
		}
		table.Execute(w, data)
	})

	// handler to serve add course page
	http.HandleFunc("/course", func(w http.ResponseWriter, r *http.Request) {
		courseNameCode.Execute(w, h)
	})

	fs := http.FileServer(http.Dir("assets/"))
	http.Handle("/static/", http.StripPrefix("/static/", fs))

	fmt.Println("Server Running at http://localhost:3000")
	utils.HandleError(http.ListenAndServe(":3000", nil))
}


package utils

import (
	"fmt"
	"regexp"
	"strings"

	"github.com/xuri/excelize/v2"
)

const (
	startRow = 7
	endRow   = 147
)

var dayofweek = []string{
	"Timings",
	"Monday",
	"Tuesday",
	"Wednesday",
	"Thursday",
	"Friday",
}

type Data struct {
	Course string `json:"course"`
	Color  string `json:"color"`
}

func (d *Data) Append(cell string, regex *Regexs) {
	cellbyte := regex.Sub.ReplaceAllStringFunc(cell, func(data string) string {
		str := strings.ReplaceAll(data, "/", "")
		str = strings.ReplaceAll(str, " ", "")
		if len(str) > 6 {
			str = strings.TrimRightFunc(str, func(s rune) bool {
				if s == 'L' || s == 'P' || s == 'T' {
					return true
				} else {
					return false
				}
			})
		}
		res := GetSubjectName(str)
		if res != "" {
			return res
		} else {
			return data
		}
	})
	lres := regex.Lecture.MatchString(cell)
	tres := regex.Tut.MatchString(cell)
	eres := regex.Elective.MatchString(cell)
	if lres {
		d.Color = "danger"
	} else if tres {
		d.Color = "primary"
	} else if eres {
		d.Color = "info"
	}
	d.Course += cellbyte
}

type Regexs struct {
	Lecture  *regexp.Regexp
	Tut      *regexp.Regexp
	Elective *regexp.Regexp
	Sub      *regexp.Regexp
}

func GetTableData(sheet string, class int, f *excelize.File) [][]Data {
	// regexs
	lecture, _ := regexp.Compile(`^[A-Z]{3}[0-9]{3}\s?L`)
	tut, _ := regexp.Compile(`^[A-Z]{3}[0-9]{3}\s?T`)
	elective, _ := regexp.Compile(`^([A-Z]{3}[0-9]{3}(\/[A-Z]{3}[0-9]{3})+)\s?L`)
	subSelect, _ := regexp.Compile(`[A-Z]{3}[0-9]{3}\s?[L,T,P]?`)

	regex := Regexs{lecture, tut, elective, subSelect}
	timings := [][]Data{}
	freeTime := Data{Course: "", Color: "success"}
	var Days []Data
	for _, d := range dayofweek {
		temp := Data{
			Course: d,
			Color:  "dark",
		}
		Days = append(Days, temp)
	}

	col, err := excelize.ColumnNumberToName(class)
	HandleError(err)
	timeValue := []string{"8:00am", " 8:50:am", "9:40:am", "10:30:am", "11:20am", "12:10pm", "1:00pm", "1:50pm", "2:40pm", "3:30pm", "4:20pm", "5:10pm", "6:00pm", "6:50pm"}

	tempMap := []Data{}

	check := ""
	for i := startRow; i < endRow; i += 2 {
		timeCell := fmt.Sprintf("D%d", i)
		time, _ := f.GetCellValue(sheet, timeCell)
		time = strings.ToLower(time)
		time = strings.ReplaceAll(time, " ", "")
		tclass := class
		var temp Data
		for j := 0; j < 2; j++ {
			cellId := fmt.Sprintf("%s%d", col, i+j)
			cell, _ := f.GetCellValue(sheet, cellId)
			if check == cell && check != "" && cell != "" {
				cell = "Lab Continue"
			} else {
				check = cell
			}
			if cell != "" {
				if temp.Course != "" && strings.Trim(cell, " ") == strings.Trim(temp.Course, " ") {
					continue
				}
				if j == 1 && cell == "Lab Continue" {
					continue
				}
				temp.Append(cell+" ", &regex)
			} else {
				// algo to get venue in a merged cell situation
				if temp.Course != "" && j == 1 {
					tcell := ""
					maxIter := 35 //to prevent infinite loop
					for tcell == "" && maxIter > 0 {
						tclass--
						col, err := excelize.ColumnNumberToName(tclass)
						HandleError(err)
						cellId := fmt.Sprintf("%s%d", col, i+j)
						tcell, err = f.GetCellValue(sheet, cellId)
						HandleError(err)
						if tcell != "" {
							temp.Append(tcell, &regex)
							break
						}
						maxIter--
					}
				}
				temp.Append("", &regex)
			}
		}
		if temp.Course == "" {
			tempMap = append(tempMap, freeTime)
		} else {
			tempMap = append(tempMap, temp)
		}
		if time == "6:50pm" {
			timings = append(timings, tempMap)
			tempMap = []Data{}
		}
	}

	newtimings := [][]Data{}
	newtimings = append(newtimings, Days)
	for i := 0; i < 14; i++ {
		temp := []Data{}
		temp = append(temp, Data{timeValue[i], "dark"})
		for _, d := range timings {
			temp = append(temp, d[i])
		}
		newtimings = append(newtimings, temp)
	}

	return newtimings
}


package utils

import (
	"encoding/json"
	"os"
	"strings"

	"github.com/xuri/excelize/v2"
)

func GenerateJson() {
	f, err := excelize.OpenFile("timetable.xlsx")
	defer func() {
		if err = f.Close(); err != nil {
			panic(err)
		}
	}()
	HandleError(err)
	sheets := f.GetSheetList()
	classes := make(map[string]map[int]string)
	for _, sheet := range sheets {
		temp := make(map[int]string)
		rows, err := f.GetRows(sheet)
		for i, d := range rows {
			if i == 3 {
				for j, k := range d {
					if k != "" && k != "DAY" && k != "HOURS" && k != "SR NO" && k != "SR.NO" && k != "TUTORIAL" {
						temp[j+1] = k
					}
				}
			}
		}
		classes[sheet] = temp
		HandleError(err)
	}
	ExcelToJson(classes, f)
}

func ExcelToJson(classes map[string]map[int]string, f *excelize.File) {
	file, err := os.OpenFile("./data.json", os.O_TRUNC|os.O_WRONLY, os.ModeAppend)
	HandleError(err)
	defer file.Close()
	data := make(map[string]map[string][][]Data)
	for i, d := range classes {
		temp := make(map[string][][]Data)
		for j, k := range d {
			tc := GetTableData(i, j, f)
			temp[strings.Trim(k, " ")] = tc
		}
		data[strings.Trim(i, " ")] = temp
	}
	dj, _ := json.MarshalIndent(data, "", "	")
	_, err = file.Write(dj)
	HandleError(err)
}

package utils

import (
	"encoding/json"
	"io"
	"os"
)

type SubjectData struct {
	SerialNumber int
	Name         string
	Code         string
	Credit       string
	IsCore       bool
}

var SubjectMap map[string]string

func GetSubjectMapping() {
	file, err := os.Open("./subjects.json")
	HandleError(err)
	defer file.Close()

	fileData := make(map[string]SubjectData)
	fileBytes, err := io.ReadAll(file)
	HandleError(err)
	json.Unmarshal(fileBytes, &fileData)

	// fileData contains json data of subjects
	// need to extract key and name value

	subjectMapping := make(map[string]string)

	for i, d := range fileData {
		subjectMapping[i] = d.Name
	}
	SubjectMap = subjectMapping
}

func GetSubjectName(code string) string {
	return SubjectMap[code]
}


make a python code for the same and generate a complete xlsx to formatted json file for this