瀏覽代碼

Add files

Number571 5 年之前
父節點
當前提交
54643b3ee3
共有 100 個文件被更改,包括 7202 次插入0 次删除
  1. 8 0
      .idea/ScheduleAPI.iml
  2. 6 0
      .idea/misc.xml
  3. 8 0
      .idea/modules.xml
  4. 6 0
      .idea/vcs.xml
  5. 76 0
      .idea/workspace.xml
  6. 1 0
      Schedule
  7. 1 0
      ScheduleGenerator
  8. 84 0
      api/attestation.go
  9. 26 0
      api/authorization.go
  10. 106 0
      api/bellschedule.go
  11. 149 0
      api/classroom.go
  12. 110 0
      api/group.go
  13. 76 0
      api/management.go
  14. 134 0
      api/models.go
  15. 35 0
      api/scheduleGenerator.go
  16. 124 0
      api/scheduleOfGroup.go
  17. 127 0
      api/scheduletemplate.go
  18. 81 0
      api/semester.go
  19. 101 0
      api/specialty.go
  20. 105 0
      api/studyplan.go
  21. 248 0
      api/subject.go
  22. 112 0
      api/subjectOfGroup.go
  23. 106 0
      api/subjectofplan.go
  24. 106 0
      api/subjecttype.go
  25. 105 0
      api/teacher.go
  26. 90 0
      api/token.go
  27. 28 0
      color/color.go
  28. 11 0
      html/404.html
  29. 114 0
      html/api.html
  30. 347 0
      html/bellschedule.html
  31. 155 0
      html/classroom.html
  32. 142 0
      html/cycle.html
  33. 175 0
      html/group.html
  34. 335 0
      html/groupcard.html
  35. 15 0
      html/head.html
  36. 352 0
      html/index.html
  37. 94 0
      html/log in.html
  38. 9 0
      html/log.html
  39. 85 0
      html/login.html
  40. 48 0
      html/nav.html
  41. 199 0
      html/schedule.html
  42. 149 0
      html/specialty.html
  43. 158 0
      html/subject.html
  44. 148 0
      html/teacher.html
  45. 377 0
      html/teacherscard.html
  46. 110 0
      input/groups.json
  47. 41 0
      input/teachers.json
  48. 0 0
      log/R0R2CL~J.LOG
  49. 0 0
      log/RBFZWE~V.LOG
  50. 0 0
      log/RS83M3~S.LOG
  51. 0 0
      log/RXYWKY~C.LOG
  52. 3 0
      log/Requests_API.log
  53. 3 0
      log/Requests_URL.log
  54. 0 0
      log/error.log
  55. 二進制
      main
  56. 179 0
      main.go
  57. 109 0
      models.txt
  58. 353 0
      schedule/generator.go
  59. 609 0
      schedule/localdata.go
  60. 102 0
      schedule/models.go
  61. 18 0
      schedule/settings.go
  62. 29 0
      settings/settings.go
  63. 二進制
      static/assets/banners/default_300x250.jpg
  64. 二進制
      static/assets/banners/default_300x600.jpg
  65. 二進制
      static/assets/banners/default_728x90.jpg
  66. 64 0
      static/assets/email/action.html
  67. 68 0
      static/assets/email/alert.html
  68. 95 0
      static/assets/email/billing.html
  69. 二進制
      static/assets/email/logo.png
  70. 二進制
      static/assets/email/preview/action.png
  71. 二進制
      static/assets/email/preview/alert.png
  72. 二進制
      static/assets/email/preview/billing.png
  73. 288 0
      static/assets/email/styles.css
  74. 二進制
      static/assets/header/header-1.jpg
  75. 二進制
      static/assets/header/header-2.jpg
  76. 1 0
      static/assets/html/calendar_ajax.html
  77. 58 0
      static/assets/html/preview_ajax.html
  78. 二進制
      static/assets/images/background/bg-1.jpg
  79. 二進制
      static/assets/images/landing/header_background.fw.png
  80. 二進制
      static/assets/images/landing/header_background.jpg
  81. 二進制
      static/assets/images/landing/layouts.png
  82. 二進制
      static/assets/images/landing/presentation.png
  83. 二進制
      static/assets/images/landing/responsive.png
  84. 二進制
      static/assets/images/large/img-1.jpg
  85. 二進制
      static/assets/images/large/img-10.jpg
  86. 二進制
      static/assets/images/large/img-11.jpg
  87. 二進制
      static/assets/images/large/img-12.jpg
  88. 二進制
      static/assets/images/large/img-2.jpg
  89. 二進制
      static/assets/images/large/img-3.jpg
  90. 二進制
      static/assets/images/large/img-4.jpg
  91. 二進制
      static/assets/images/large/img-5.jpg
  92. 二進制
      static/assets/images/large/img-6.jpg
  93. 二進制
      static/assets/images/large/img-7.jpg
  94. 二進制
      static/assets/images/large/img-8.jpg
  95. 二進制
      static/assets/images/large/img-9.jpg
  96. 二進制
      static/assets/images/news/business_1.jpg
  97. 二進制
      static/assets/images/news/business_2.jpg
  98. 二進制
      static/assets/images/news/business_3.jpg
  99. 二進制
      static/assets/images/news/city_1.jpg
  100. 0 0
      static/assets/images/news/city_2.jpg

+ 8 - 0
.idea/ScheduleAPI.iml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 6 - 0
.idea/misc.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JavaScriptSettings">
+    <option name="languageLevel" value="ES6" />
+  </component>
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/ScheduleAPI.iml" filepath="$PROJECT_DIR$/.idea/ScheduleAPI.iml" />
+    </modules>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$/ScheduleGenerator" vcs="Git" />
+  </component>
+</project>

+ 76 - 0
.idea/workspace.xml

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ChangeListManager">
+    <list default="true" id="b8a967e5-9651-44eb-87a6-16760f979b45" name="Default Changelist" comment="">
+      <change beforePath="$PROJECT_DIR$/ScheduleGenerator/LICENSE" beforeDir="false" afterPath="$PROJECT_DIR$/ScheduleGenerator/LICENSE" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/ScheduleGenerator/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/ScheduleGenerator/README.md" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/ScheduleGenerator/input/groups.json" beforeDir="false" afterPath="$PROJECT_DIR$/ScheduleGenerator/input/groups.json" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/ScheduleGenerator/input/teachers.json" beforeDir="false" afterPath="$PROJECT_DIR$/ScheduleGenerator/input/teachers.json" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/ScheduleGenerator/main.go" beforeDir="false" afterPath="$PROJECT_DIR$/ScheduleGenerator/main.go" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/ScheduleGenerator/output/schedule.xlsx" beforeDir="false" afterPath="$PROJECT_DIR$/ScheduleGenerator/output/schedule.xlsx" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/ScheduleGenerator/schedule/generator.go" beforeDir="false" afterPath="$PROJECT_DIR$/ScheduleGenerator/schedule/generator.go" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/ScheduleGenerator/schedule/localdata.go" beforeDir="false" afterPath="$PROJECT_DIR$/ScheduleGenerator/schedule/localdata.go" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/ScheduleGenerator/schedule/models.go" beforeDir="false" afterPath="$PROJECT_DIR$/ScheduleGenerator/schedule/models.go" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/ScheduleGenerator/schedule/settings.go" beforeDir="false" afterPath="$PROJECT_DIR$/ScheduleGenerator/schedule/settings.go" afterDir="false" />
+    </list>
+    <option name="SHOW_DIALOG" value="false" />
+    <option name="HIGHLIGHT_CONFLICTS" value="true" />
+    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+    <option name="LAST_RESOLUTION" value="IGNORE" />
+  </component>
+  <component name="FileTemplateManagerImpl">
+    <option name="RECENT_TEMPLATES">
+      <list>
+        <option value="Go File" />
+      </list>
+    </option>
+  </component>
+  <component name="GOROOT" path="/usr/lib/go-1.12" />
+  <component name="Git.Settings">
+    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/ScheduleGenerator" />
+  </component>
+  <component name="GoLibraries">
+    <option name="indexEntireGoPath" value="false" />
+  </component>
+  <component name="ProjectId" id="1YHJ2vSULrwvl6h5lxSsZ9HGGXG" />
+  <component name="ProjectViewState">
+    <option name="hideEmptyMiddlePackages" value="true" />
+    <option name="showExcludedFiles" value="true" />
+    <option name="showLibraryContents" value="true" />
+  </component>
+  <component name="PropertiesComponent">
+    <property name="DefaultGoTemplateProperty" value="Go File" />
+    <property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
+    <property name="WebServerToolWindowFactoryState" value="false" />
+    <property name="go.import.settings.migrated" value="true" />
+    <property name="go.sdk.automatically.set" value="true" />
+    <property name="go.vendoring.notification.had.been.shown" value="true" />
+    <property name="last_opened_file_path" value="$PROJECT_DIR$" />
+    <property name="settings.editor.selected.configurable" value="editor.preferences.fonts.default" />
+  </component>
+  <component name="TypeScriptGeneratedFilesManager">
+    <option name="version" value="1" />
+  </component>
+  <component name="WindowStateProjectService">
+    <state x="555" y="214" width="802" height="672" key="#GOROOT" timestamp="1582790965153">
+      <screen x="0" y="25" width="1920" height="1055" />
+    </state>
+    <state x="555" y="214" width="802" height="672" key="#GOROOT/0.25.1920.1055@0.25.1920.1055" timestamp="1582790965153" />
+    <state x="418" y="211" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1582779582584">
+      <screen x="0" y="25" width="1920" height="1055" />
+    </state>
+    <state x="418" y="211" key="#com.intellij.execution.impl.EditConfigurationsDialog/0.25.1920.1055@0.25.1920.1055" timestamp="1582779582584" />
+    <state x="557" y="148" width="797" height="804" key="CommitChangelistDialog2" timestamp="1582779607590">
+      <screen x="0" y="25" width="1920" height="1055" />
+    </state>
+    <state x="557" y="148" width="797" height="804" key="CommitChangelistDialog2/0.25.1920.1055@0.25.1920.1055" timestamp="1582779607590" />
+    <state x="743" y="311" width="426" height="479" key="FileChooserDialogImpl" timestamp="1582792657934">
+      <screen x="0" y="25" width="1920" height="1055" />
+    </state>
+    <state x="743" y="311" width="426" height="479" key="FileChooserDialogImpl/0.25.1920.1055@0.25.1920.1055" timestamp="1582792657934" />
+    <state x="464" y="188" key="SettingsEditor" timestamp="1582692089783">
+      <screen x="0" y="25" width="1920" height="1055" />
+    </state>
+    <state x="464" y="188" key="SettingsEditor/0.25.1920.1055@0.25.1920.1055" timestamp="1582692089783" />
+  </component>
+</project>

+ 1 - 0
Schedule

@@ -0,0 +1 @@
+Subproject commit 9a8a5e51a1bdffd32eb5b903994080fd2abc2d6f

+ 1 - 0
ScheduleGenerator

@@ -0,0 +1 @@
+Subproject commit aa2ba3a2be91af8da988037ca78834752de757f1

+ 84 - 0
api/attestation.go

@@ -0,0 +1,84 @@
+package api
+
+import (
+	"../settings"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+	// "strings"
+)
+
+var attestations []Attestation
+
+func AttestationRoute(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+
+	if r.Method == "UPDATE" || r.Method == "PATCH" {
+		UpdateAttestation(w, r)
+		return
+	}
+
+	path := replacePath(r.URL.Path, "/api/attestation/")
+
+	if path == "" {
+		GetAttestations(w, r)
+		return
+	}
+
+	num, err := strconv.Atoi(path)
+
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Find(&attestations)
+	if num < 0 || num > len(attestations)+1 {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+
+	if r.Method == "GET" {
+		GetAttestationById(w, r, num)
+		return
+	}
+
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "This method is not supported"})
+}
+
+func UpdateAttestation(w http.ResponseWriter, r *http.Request) {
+	var attestation Attestation
+	var AttestationToUpdate Attestation
+	err := json.NewDecoder(r.Body).Decode(&attestation)
+
+	if err != nil {
+		showError(r, err)
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update Attestation"})
+		return
+	}
+	settings.DB.First(&AttestationToUpdate, attestation.ID)
+	settings.DB.Model(&AttestationToUpdate).Updates(attestation)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "updated Attestation"})
+	return
+}
+
+func GetAttestationById(w http.ResponseWriter, r *http.Request, num int) {
+	var Attestation Attestation
+	settings.DB.Where("id = ?", num).First(&Attestation)
+	json.NewEncoder(w).Encode(Attestation)
+	return
+}
+
+func GetAttestations(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+	if r.Method == "GET" {
+		var Attestations []Attestation
+		settings.DB.Find(&Attestations)
+		json.NewEncoder(w).Encode(Attestations)
+	}
+	return
+}

+ 26 - 0
api/authorization.go

@@ -0,0 +1,26 @@
+package api
+
+// import(
+// 	"github.com/jtblin/go-ldap-client"
+// )
+
+// func GetUser(login string, password string) bool{
+
+// 	ok, user, err := clientLDAP.Authenticate(login, password)
+// 	if err != nil {
+// 		printError(err)
+// 		return false
+// 	}
+// 	if !ok {
+// 		return false
+// 	}
+// 	return true
+// }
+
+// func GetGroupOfUser(login string) []string{
+// 	groups, err := client.GetGroupsOfUser(login)
+// 	if err != nil {
+// 		printError(err)
+// 	}
+// 	return groups
+// }

+ 106 - 0
api/bellschedule.go

@@ -0,0 +1,106 @@
+package api
+
+import (
+	"../settings"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+	
+	// "strings"
+)
+
+var Lessons []Lesson
+
+func BellScheduleRoute(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+
+	if r.Method == "POST" {
+		CreateLesson(w, r)
+		return
+	}
+
+	if r.Method == "UPDATE" || r.Method == "PATCH" {
+		UpdateLesson(w, r)
+		return
+	}
+
+	path := replacePath(r.URL.Path, "/api/bellschedule/")
+
+	if path == "" {
+		GetLessons(w, r)
+		return
+	}
+
+	num, err := strconv.Atoi(path)
+
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Find(&Lessons)
+	if num < 0 || num > len(Lessons)+1 {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+
+	if r.Method == "GET" {
+		//db.Where("name = ?", "jinzhu").First(&user)
+		GetLessonById(w, r, num)
+		return
+	}
+
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "This method is not supported"})
+}
+
+func UpdateLesson(w http.ResponseWriter, r *http.Request) {
+	var lesson Lesson
+	var LessonToUpdate Lesson
+	err := json.NewDecoder(r.Body).Decode(&lesson)
+
+	
+
+	if err != nil {
+		showError(r, err)
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update Lesson"})
+		return
+	}
+	settings.DB.First(&LessonToUpdate, lesson.ID)
+	settings.DB.Model(&LessonToUpdate).Updates(lesson)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "updated Lesson"})
+	return
+}
+
+func CreateLesson(w http.ResponseWriter, r *http.Request) {
+	var newLesson Lesson
+	err := json.NewDecoder(r.Body).Decode(&newLesson)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new Lesson"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Create(&newLesson)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "added new Lesson"})
+	return
+}
+
+func GetLessonById(w http.ResponseWriter, r *http.Request, num int) {
+	var Lesson Lesson
+	settings.DB.Where("id = ?", num).First(&Lesson)
+	json.NewEncoder(w).Encode(Lesson)
+	return
+}
+
+func GetLessons(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+	if r.Method == "GET" {
+		var Lessons1 []Lesson
+		settings.DB.Find(&Lessons1)
+		json.NewEncoder(w).Encode(Lessons1)
+	}
+	return
+}

+ 149 - 0
api/classroom.go

@@ -0,0 +1,149 @@
+package api
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+	"strings"
+
+	"../settings"
+)
+
+// var Classrooms = []Classroom
+
+func CreateClassroom(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	var newClassroom Classroom
+	err := json.NewDecoder(r.Body).Decode(&newClassroom)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new classroom"})
+		showError(r, err)
+		return
+	}
+	settings.DB.Create(&newClassroom)
+	fmt.Println(newClassroom)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "added new classroom"})
+	return
+}
+
+func GetBuilding(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+	path := r.URL.Path
+	path = strings.Replace(path, "/api/building/", "", 1)
+
+	if path == "" {
+		var buildings []Building
+		settings.DB.Find(&buildings)
+		json.NewEncoder(w).Encode(buildings)
+		return
+	}
+	var building Building
+	settings.DB.Where("id = ?", path).First(&building)
+
+	json.NewEncoder(w).Encode(building)
+}
+
+func ClassroomByNumber(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+	showAPIRequest(r)
+
+	if r.Method == "GET" {
+		var classroom Classroom
+		path := r.URL.Path
+		path = strings.Replace(path, "/api/classroom/name/", "", 1)
+
+		settings.DB.Where("name = ?", path).First(&classroom)
+
+		json.NewEncoder(w).Encode(classroom)
+		return
+	}
+}
+
+func UpdateClassroom(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	var newClassroom Classroom
+	err := json.NewDecoder(r.Body).Decode(&newClassroom)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update Classroom"})
+		fmt.Println(err)
+		return
+	}
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "Successfully updated Classroom"})
+	return
+}
+
+func ClassroomRoute(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+
+	if r.Method == "POST" {
+		CreateClassroom(w, r)
+		return
+	}
+
+	if r.Method == "UPDATE" || r.Method == "PATCH" {
+		UpdateClassroom(w, r)
+		return
+	}
+
+	if replacePath(r.URL.Path, "/api/classroom/") == "" {
+		GetClassrooms(w, r)
+		return
+	}
+
+	if r.Method == "GET" {
+		if replacePath(r.URL.Path, "/api/classroom/") == "" {
+			GetClassrooms(w, r)
+			return
+		}
+		GetClassroom(w, r)
+		return
+	}
+
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "This method is not supported"})
+}
+
+func GetClassroom(w http.ResponseWriter, r *http.Request) {
+	path := replacePath(r.URL.Path, "/api/classroom/")
+	num, err := strconv.Atoi(path)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		showError(r, err)
+		return
+	}
+	var room Classroom
+	settings.DB.Where("id = ?", num).First(&room)
+	json.NewEncoder(w).Encode(room)
+}
+
+func GetClassrooms(w http.ResponseWriter, r *http.Request) {
+	if r.Method == "GET" {
+		var classrooms []Classroom
+		settings.DB.Find(&classrooms)
+		json.NewEncoder(w).Encode(classrooms)
+		return
+	}
+}
+
+func GetClassroomByComputer(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+	if r.Method == "GET" {
+		path := r.URL.Path
+		path = strings.Replace(path, "/api/classroom/", "", 1)
+		if path == "computer" {
+			var Classrooms []Classroom
+			settings.DB.Where("iscomputer = ?", true).Find(&Classrooms)
+			json.NewEncoder(w).Encode(Classrooms)
+			return
+		}
+		if path == "lecture" {
+			var Classrooms []Classroom
+			settings.DB.Where("iscomputer = ?", false).Find(&Classrooms)
+			json.NewEncoder(w).Encode(Classrooms)
+			return
+		}
+	}
+}

+ 110 - 0
api/group.go

@@ -0,0 +1,110 @@
+package api
+
+import (
+	"../settings"
+	"encoding/json"
+	"net/http"
+	"strconv"
+	"strings"
+)
+
+var Groups = make(map[uint]Group)
+
+func CreateGroup(w http.ResponseWriter, r *http.Request) {
+	var newGroup Group
+	err := json.NewDecoder(r.Body).Decode(&newGroup)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new Group"})
+		return
+	}
+	settings.DB.Create(&newGroup)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "added new Group"})
+	return
+}
+
+func UpdateGroup(w http.ResponseWriter, r *http.Request) {
+	var newGroup Group
+	err := json.NewDecoder(r.Body).Decode(&newGroup)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update Group"})
+		return
+	}
+	if _, ok := Groups[newGroup.ID]; !ok {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update Group"})
+		return
+	}
+	Groups[newGroup.ID] = newGroup
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "Successfully updated Group"})
+	return
+}
+
+func GroupRoute(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+
+	if r.Method == "POST" {
+		CreateGroup(w, r)
+	}
+
+	if r.Method == "UPDATE" || r.Method == "PATCH" {
+		UpdateGroup(w, r)
+	}
+
+	path := replacePath(r.URL.Path, "/api/group/")
+
+	if path == "" && r.Method == "GET"{
+		GetGroups(w, r)
+		return
+	}
+
+	if r.Method == "GET" {
+		GetGroup(w, r)
+		return
+	}
+
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "It is not GET method"})
+}
+
+func GetGroups(w http.ResponseWriter, r *http.Request){
+	var output []Group
+	settings.DB.Find(&output)
+	json.NewEncoder(w).Encode(output)
+}
+
+func GetGroup(w http.ResponseWriter, r *http.Request) {
+	path := replacePath(r.URL.Path, "/api/group/")
+	num, err := strconv.Atoi(path)
+
+	if err != nil || num < 0 {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		return
+	}
+
+	var groups Group
+	settings.DB.Where("id = ?", num).First(&groups)
+	json.NewEncoder(w).Encode(groups)
+	return
+}
+
+func GetGroupBySpecialty(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+	if r.Method == "GET" {
+		path := r.URL.Path
+		path = strings.Replace(path, "/api/group/specialty/", "", 1)
+		var output []Group
+
+		num, err := strconv.Atoi(path)
+
+		if err != nil || num < 0 {
+			json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		}
+
+		for _, group := range Groups {
+			if group.IDSpecialty == uint(num) {
+				output = append(output, group)
+			}
+		}
+		json.NewEncoder(w).Encode(output)
+	}
+}

+ 76 - 0
api/management.go

@@ -0,0 +1,76 @@
+package api
+
+import (
+	"../color"
+	"../settings"
+	"fmt"
+	"net/http"
+	"os"
+	"strings"
+	"time"
+)
+
+func showAPIRequest(r *http.Request) {
+	t := time.Now()
+	fmt.Println("[", t.Format(settings.TimeLayout), "] ", color.Green, r.Method, color.Reset, " request from ", r.RemoteAddr, " to ", r.URL.Path)
+
+	urllog, err := os.OpenFile("./log/Requests_API.log", os.O_APPEND|os.O_WRONLY, 0644)
+
+	if err != nil {
+		fmt.Println("[", t.Format(settings.TimeLayout), "]", "Error writing to API log file")
+	}
+	s := "[" + t.Format(time.Kitchen) + "] " + r.Method + " request from " + r.RemoteAddr + " to " + r.URL.Path + "\n"
+	_, err = urllog.WriteString(s)
+	if err != nil {
+		fmt.Println("[", t.Format(settings.TimeLayout), "]", "Error writing to log file")
+	}
+}
+
+func showError(r *http.Request, Err error) {
+	t := time.Now()
+	fmt.Println("[", t.Format(settings.TimeLayout), "] ", color.Red, "Error:", color.Reset, Err.Error())
+
+	errlog, err := os.OpenFile("./log/error.log", os.O_APPEND|os.O_WRONLY, 0644)
+
+	if err != nil {
+		fmt.Println("[", t.Format(settings.TimeLayout), "] ", color.Red, "Error:", color.Reset, Err.Error())
+		return
+	}
+
+	s := "[" + t.Format(settings.TimeLayout) + "] " + "Error:" + Err.Error()
+
+	_, err = errlog.WriteString(s)
+
+	if err != nil {
+		fmt.Println("[", t.Format(settings.TimeLayout), "] ", color.Red, "Error:", color.Reset, Err.Error())
+	}
+	return
+}
+
+func PrintConsole(message string) {
+	t := time.Now()
+	fmt.Println("[", t.Format(settings.TimeLayout), "] ", message)
+}
+
+func printError(Err error) {
+	t := time.Now()
+	s := "[" + t.Format(settings.TimeLayout) + "] " + "Error:" + Err.Error()
+	fmt.Println(s)
+	return
+}
+
+func replacePath(path string, replacement string) string {
+	newPath := strings.Replace(path, replacement, "", 1)
+	return newPath
+}
+
+func CheckMethod(r *http.Request, method string) bool {
+	if r.Method == method {
+		return true
+	}
+	return false
+}
+
+// func PrintToFile(){
+
+// }

+ 134 - 0
api/models.go

@@ -0,0 +1,134 @@
+package api
+
+
+
+
+
+type Professionalmodule struct {
+	ID        uint
+	Name      string
+	Shortname string
+	IDCycle   uint
+}
+
+type Cycle struct {
+	ID        uint
+	Name      string
+	Shortname string
+}
+
+type Lesson struct {
+	ID        uint
+	Timestart string
+	Timeend   string
+}
+
+type Attestation struct {
+	ID        uint
+	Name      string
+	Shortname string
+}
+
+type Subjectofgroup struct {
+	ID            uint
+	IDSubject     uint
+	IDGroup       uint
+	IDTeacher     uint
+	IDSemester    uint
+	IDAttestation uint
+	Hoursquantity uint
+}
+
+type Subject struct {
+	ID                    uint
+	Name                  string
+	Shortname             string
+	ID_professionalmodule uint
+	IDStype				  uint
+}
+
+type Group struct {
+	ID          uint
+	IDSpecialty uint
+	Year        uint
+	IDTeacher   uint
+	Groupnumber string 
+	Studentsquantity uint
+}
+
+type Semester struct {
+	ID            uint
+	Weeksquantity uint
+}
+
+type Teacher struct {
+	ID          uint
+	Name        string
+	IDClassroom uint
+	Surname     string
+	Patronymic  string
+}
+
+type Scheduleofgroup struct {
+	ID             uint
+	IDSubject      uint
+	IDGroup        uint
+	IDSchedule     uint
+	IDLessonnumber uint
+	IDClassroom    uint
+}
+
+type Schedule struct {
+	ID         uint
+	IsShort    bool
+	IDGroup    uint
+	IsEvenWeek bool
+	Weekday    string
+}
+
+type Classroom struct {
+	ID            uint
+	Placequantity uint
+	Iscomputer    bool
+	IDBuilding    uint
+	Name          string
+}
+
+type Building struct {
+	ID      uint
+	Address string
+}
+
+type Specialty struct {
+	ID         uint
+	Code       string
+	Name       string
+	IDDuration uint
+}
+
+type DurationOfStudy struct {
+	ID            uint
+	Yearsquantity uint
+}
+
+
+type Subjecttype struct {
+	ID            uint
+	Name 		  string
+}
+
+
+type Subjectofplan struct {
+	ID            uint
+	IDPlan		  uint
+	IDSubject	  uint
+	Hoursquantitytotal uint
+	idepentwork	  uint
+	consulthours  uint
+}
+
+
+type Studyplan struct {
+	ID            uint
+	IDSpecialty   uint
+}

+ 35 - 0
api/scheduleGenerator.go

@@ -0,0 +1,35 @@
+package api
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"../schedule"
+)
+
+const (
+	INDATA = "input/"
+)
+
+func Generate(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	if r.Method == "GET" {
+		var result [][]*schedule.Schedule
+		var generator = schedule.NewGenerator(&schedule.Generator{
+			Day: schedule.MONDAY,
+			// NumTables: 11,
+			Groups:   schedule.ReadGroups(INDATA + "groups.json"),
+			Teachers: schedule.ReadTeachers(INDATA + "teachers.json"),
+		})
+		for iter := 1; iter <= 7; iter++ {
+			result = append(result, generator.Generate(nil))
+		}
+		json.NewEncoder(w).Encode(result)
+	}
+}
+
+func printJSON(data interface{}) {
+	jsonData, _ := json.MarshalIndent(data, "", "\t")
+	fmt.Println(string(jsonData))
+}

+ 124 - 0
api/scheduleOfGroup.go

@@ -0,0 +1,124 @@
+package api
+
+import (
+	"../settings"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+	"strings"
+)
+
+var ScheduleOfGroups []Scheduleofgroup
+
+func ScheduleOfGroupRoute(w http.ResponseWriter, r *http.Request) {
+
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+
+	if r.Method == "POST" {
+		CreateScheduleOfGroup(w, r)
+		return
+	}
+
+	if r.Method == "UPDATE" || r.Method == "PATCH" {
+		UpdateScheduleOfGroup(w, r)
+		return
+	}
+
+	path := replacePath(r.URL.Path, "/api/groupschedule/")
+
+	if path == "" {
+		GetScheduleOfGroups(w, r)
+		return
+	}
+
+	if strings.Contains(path, "day/") {
+
+		day := strings.Replace(path, "day/", "", 1)
+		switch day {
+		case "monday", "tuesday", "wednesday", "thursday", "friday", "saturday":
+		default:
+			json.NewEncoder(w).Encode(struct{ Error string }{Error: "undefined day error"})
+			return
+		}
+
+		GetScheduleByDay(w, r, day)
+		return
+	}
+
+	num, err := strconv.Atoi(path)
+
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Find(&ScheduleOfGroups)
+	if num < 0 || num > len(ScheduleOfGroups)+1 {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+
+	if r.Method == "GET" {
+		GetScheduleOfGroupById(w, r, num)
+		return
+	}
+
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "This method is not supported"})
+}
+
+func GetScheduleByDay(w http.ResponseWriter, r *http.Request, day string) {
+	var ScheduleOfday []Schedule
+	settings.DB.Where("weekday = ?", day).Find(&ScheduleOfday)
+	json.NewEncoder(w).Encode(ScheduleOfday)
+	return
+}
+
+func UpdateScheduleOfGroup(w http.ResponseWriter, r *http.Request) {
+	var ScheduleOfGroup Scheduleofgroup
+	var ScheduleOfGroupToUpdate Scheduleofgroup
+	err := json.NewDecoder(r.Body).Decode(&ScheduleOfGroup)
+
+	if err != nil {
+		showError(r, err)
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update ScheduleOfGroup"})
+		return
+	}
+	settings.DB.First(&ScheduleOfGroupToUpdate, ScheduleOfGroup.ID)
+	settings.DB.Model(&ScheduleOfGroupToUpdate).Updates(ScheduleOfGroup)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "updated ScheduleOfGroup"})
+	return
+}
+
+func CreateScheduleOfGroup(w http.ResponseWriter, r *http.Request) {
+	var newScheduleOfGroup Scheduleofgroup
+	err := json.NewDecoder(r.Body).Decode(&newScheduleOfGroup)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new ScheduleOfGroup"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Create(&newScheduleOfGroup)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "added new ScheduleOfGroup"})
+	return
+}
+
+func GetScheduleOfGroupById(w http.ResponseWriter, r *http.Request, num int) {
+	var ScheduleOfGroup Scheduleofgroup
+	settings.DB.Where("id = ?", num).First(&ScheduleOfGroup)
+	json.NewEncoder(w).Encode(ScheduleOfGroup)
+	return
+}
+
+func GetScheduleOfGroups(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+	if r.Method == "GET" {
+		var ScheduleOfGroups []Scheduleofgroup
+		settings.DB.Find(&ScheduleOfGroups)
+		json.NewEncoder(w).Encode(ScheduleOfGroups)
+	}
+	return
+}

+ 127 - 0
api/scheduletemplate.go

@@ -0,0 +1,127 @@
+package api
+
+import (
+	"../settings"
+	"encoding/json"
+	"fmt"
+    "net/http"
+    "../schedule"
+	// "strconv"
+	// "errors"
+	// "math/rand"
+)
+
+var tmpteachers []schedule.Teacher
+var tmpcabinets []schedule.Cabinet
+
+var tmpgroups []schedule.Group
+var tmpsubjects []schedule.Subject
+// var tmplessons []schedule.LessonJSON
+
+func GetDataTeachers(w http.ResponseWriter, r *http.Request) {
+
+	var classrooms []Classroom
+	var teachers []Teacher
+	settings.DB.Find(&teachers)
+	settings.DB.Find(&classrooms)
+	var cabinet schedule.Cabinet
+	for _, room := range classrooms{
+		cabinet.Name = room.Name
+		cabinet.IsComputer = room.Iscomputer
+		tmpcabinets = append(tmpcabinets, cabinet)
+	}
+
+	for _, teacher := range teachers{
+		var scheduleTeacher schedule.Teacher
+		scheduleTeacher.Name = teacher.Name + " " + string(teacher.Surname[:2]) + "." + string(teacher.Patronymic[:2]) + "."
+		for _, room := range classrooms{
+			if teacher.IDClassroom == room.ID {
+				var tmpcabinet schedule.Cabinet
+				tmpcabinet.Name = room.Name
+				tmpcabinet.IsComputer = room.Iscomputer
+				scheduleTeacher.Cabinets = append(scheduleTeacher.Cabinets, tmpcabinet)
+				tmpcabinet = schedule.Cabinet{}
+				break 
+			}
+		}
+		tmpteachers = append(tmpteachers, scheduleTeacher) 
+	}
+
+	json.NewEncoder(w).Encode(tmpteachers)
+	return
+}
+
+func GetDataGroups(w http.ResponseWriter, r *http.Request){
+	// tmp := replacePath(r.URL.Path, "/api/getgroups/")
+	// num, err := strconv.Atoi(tmp)
+
+	// if err != nil{
+	// 	json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+	// }
+	var groups []Group
+	var subjects []Subject
+	// var tmpsubofgroup1 []Subjectofgroup
+	// var tmpsubofgroup2 []Subjectofgroup
+	var tmpsubofgroup []Subjectofgroup
+
+	settings.DB.Find(&groups)
+	settings.DB.Find(&subjects)
+	// settings.DB.Where("id_group = ?", num).Find(&tmpsubofgroup)
+
+	for _, group := range groups{
+		settings.DB.Where("id_group = ?", group.ID).Find(&tmpsubofgroup)
+
+		var tmpgroup schedule.Group
+		tmpgroup.Name = group.Groupnumber
+		tmpgroup.Quantity = group.Studentsquantity
+		for _, subject := range tmpsubofgroup{
+			// scheduleTeacher.Name = teacher.Name + " " + string(teacher.Surname[:2]) + "." + string(teacher.Patronymic[:2]) + "."
+			var tmpsubject schedule.Subject
+			var tsubject Subject
+			var teacher Teacher
+			var semester Semester
+			settings.DB.Where("id = ?", subject.ID).First(&tsubject)
+			settings.DB.Where("id = ?", subject.IDTeacher).First(&teacher)
+			settings.DB.Where("id = ?", subject.IDSemester).First(&semester)
+			tmpsubject.Name = tsubject.Shortname
+			tmpsubject.Teacher = teacher.Name + " " + string(teacher.Surname[:2]) + "." + string(teacher.Patronymic[:2]) + "."
+			tmpsubject.Teacher2 = tmpsubject.Teacher // TODO
+			if tsubject.IDStype == 1{
+				tmpsubject.IsComputer = false
+				tmpsubject.Theory = 0
+				tmpsubject.Practice.A = subject.Hoursquantity/2
+				tmpsubject.Practice.B = subject.Hoursquantity/2
+			} else if tsubject.IDStype == 0{
+				tmpsubject.IsComputer = true
+				tmpsubject.Theory = subject.Hoursquantity/2
+				tmpsubject.Practice.A = 0
+				tmpsubject.Practice.B = 0
+			}
+			fmt.Println(semester)
+			tmpsubject.WeekLessons.A = (subject.Hoursquantity/semester.Weeksquantity)/2
+			tmpsubject.WeekLessons.B = (subject.Hoursquantity/semester.Weeksquantity)/2
+			tmpsubjects = append(tmpsubjects, tmpsubject)
+		}
+	}
+
+	// for i, sub := range tmpsubofgroup1{
+	// 	var subof Subjectofgroup
+	// 	for j, gr := range tmpsubofgroup2{
+	// 		if gr == sub{
+	// 			subof = gr
+	// 			tmpsubofgroup1 = append(tmpsubofgroup1[:i], tmpsubofgroup[i+1:]...)
+	// 			tmpsubofgroup2 = append(tmpsubofgroup1[:j], tmpsubofgroup[j+1:]...)
+	// 			break
+	// 		}
+	// 	}
+	// 	tmpsubofgroup = append(tmpsubofgroup, subof)
+	// 	subof = Subjectofgroup{}
+	// }
+
+	json.NewEncoder(w).Encode(tmpsubjects)
+	// for _, subject := range subjects{
+	// 	var tmpsubject schedue.Subject
+	// 	tmpsubject.Name = subject.ShortName
+	// 	tmpsubject.teacher = 
+	// }
+}

+ 81 - 0
api/semester.go

@@ -0,0 +1,81 @@
+package api
+
+import (
+	"../settings"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+	"strings"
+)
+
+var Semesters []Semester
+
+func SemesterRoute(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+
+	path := replacePath(r.URL.Path, "/api/semester/")
+	num, err := strconv.Atoi(path)
+
+	if path == "" {
+		GetSemesters(w, r)
+		return
+	}
+
+	if strings.Contains(path, "day/") {
+		GetSemestersByWeeks(w, r)
+		return
+	}
+
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Find(&Semesters)
+	if num < 0 || num > len(Semesters)+1 {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+
+	if r.Method == "GET" {
+		GetSemesterById(w, r, num)
+		return
+	}
+
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "This method is not supported"})
+}
+
+func GetSemestersByWeeks(w http.ResponseWriter, r *http.Request) {
+	path := replacePath(r.URL.Path, "/api/semester/weeks/")
+
+	num, err := strconv.Atoi(path)
+	if err != nil || num < 0 {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+	}
+
+	var semesters []Semester
+	settings.DB.Where("weeksquantity = ?", num).Find(&semesters)
+	json.NewEncoder(w).Encode(semesters)
+	return
+}
+
+func GetSemesterById(w http.ResponseWriter, r *http.Request, num int) {
+	var Semester Semester
+	settings.DB.Where("id = ?", num).First(&Semester)
+	json.NewEncoder(w).Encode(Semester)
+	return
+}
+
+func GetSemesters(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+	if r.Method == "GET" {
+		var Semesters []Semester
+		settings.DB.Find(&Semesters)
+		json.NewEncoder(w).Encode(Semesters)
+	}
+	return
+}

+ 101 - 0
api/specialty.go

@@ -0,0 +1,101 @@
+package api
+
+import (
+	"../settings"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+)
+
+func CreateSpecialty(w http.ResponseWriter, r *http.Request) {
+	var newSpecialty Specialty
+	err := json.NewDecoder(r.Body).Decode(&newSpecialty)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new Specialty"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Create(&newSpecialty)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "added new Specialty"})
+	return
+}
+
+func GetSpecialty(w http.ResponseWriter, r *http.Request) {
+	var Specialty Specialty
+	path := replacePath(r.URL.Path, "/api/specialty/")
+	num, err := strconv.Atoi(path)
+	if err != nil {
+		showError(r, err)
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		return
+	}
+	settings.DB.Where("id = ?", num).First(&Specialty)
+	json.NewEncoder(w).Encode(Specialty)
+	return
+}
+
+func GetSpecialties(w http.ResponseWriter, r *http.Request) {
+	var Specialties []Specialty
+	settings.DB.Find(&Specialties)
+	json.NewEncoder(w).Encode(Specialties)
+}
+
+func UpdateSpecialty(w http.ResponseWriter, r *http.Request) {
+	var specialty Teacher
+	var specialtyToUpdate Teacher
+	err := json.NewDecoder(r.Body).Decode(&specialty)
+
+	if err != nil {
+		showError(r, err)
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update specialty"})
+		return
+	}
+	settings.DB.First(&specialtyToUpdate, specialty.ID)
+	settings.DB.Model(&specialtyToUpdate).Updates(specialty)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "updated specialty"})
+	return
+}
+
+func SpecialtyRoute(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+
+	if r.Method == "POST" {
+		CreateSpecialty(w, r)
+		return
+	}
+
+	if r.Method == "UPDATE" || r.Method == "PATCH" {
+		UpdateSpecialty(w, r)
+		return
+	}
+
+	path := replacePath(r.URL.Path, "/api/specialty/")
+
+	if path == "" && r.Method == "GET" {
+		GetSpecialties(w, r)
+		return
+	}
+
+	num, err := strconv.Atoi(path)
+
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+
+	if num < 0 {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+
+	if r.Method == "GET" {
+		GetSpecialty(w, r)
+		return
+	}
+
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "It is not GET method"})
+}

+ 105 - 0
api/studyplan.go

@@ -0,0 +1,105 @@
+package api
+
+import (
+	"../settings"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+)
+
+var studyplan []Studyplan
+
+func StudyplanRoute(w http.ResponseWriter, r *http.Request) {
+	
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+
+	if r.Method == "POST" {
+		CreateStudyPlan(w, r)
+		return
+	}
+
+	
+	if r.Method == "UPDATE" || r.Method == "PATCH" {
+		UpdateStudyPlan(w, r)
+		return
+	}
+
+	
+	path := replacePath(r.URL.Path, "/api/studyplan/")
+
+	if path == "" {
+		GetStudyPlan(w, r)
+		return
+	}
+	
+
+	num, err := strconv.Atoi(path)
+
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Find(&ScheduleOfGroups)
+	if num < 0 || num > len(ScheduleOfGroups)+1 {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+
+	if r.Method == "GET" {
+		GetStudyPlanById(w, r, num)
+		return
+	}
+
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "This method is not supported"})
+}
+
+func UpdateStudyPlan(w http.ResponseWriter, r *http.Request) {
+	var StudyPlan Studyplan
+	var StudyplanToUpdate Studyplan
+	err := json.NewDecoder(r.Body).Decode(&StudyPlan)
+
+	if err != nil {
+		showError(r, err)
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update StudyPlan"})
+		return
+	}
+	settings.DB.First(&StudyplanToUpdate, StudyPlan.ID)
+	settings.DB.Model(&StudyplanToUpdate).Updates(StudyPlan)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "updated StudyPlan"})
+	return
+}
+
+func CreateStudyPlan(w http.ResponseWriter, r *http.Request) {
+	var newStudyPlan Studyplan
+	err := json.NewDecoder(r.Body).Decode(&newStudyPlan)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new StudyPlan"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Create(&newStudyPlan)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "added new StudyPlan"})
+	return
+}
+
+func GetStudyPlanById(w http.ResponseWriter, r *http.Request, num int) {
+	var StudyPlan Studyplan
+	settings.DB.Where("id = ?", num).First(&StudyPlan)
+	json.NewEncoder(w).Encode(StudyPlan)
+	return
+}
+
+func GetStudyPlan(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+	if r.Method == "GET" {
+		var StudyPlan []Studyplan
+		settings.DB.Find(&StudyPlan)
+		json.NewEncoder(w).Encode(StudyPlan)
+	}
+	return
+}

+ 248 - 0
api/subject.go

@@ -0,0 +1,248 @@
+package api
+
+import (
+	"../settings"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+	"strings"
+)
+
+func CreateSubject(w http.ResponseWriter, r *http.Request) {
+	var newSubject Subject
+	err := json.NewDecoder(r.Body).Decode(&newSubject)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new Subject"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Create(&newSubject)
+	// if err != nil {
+	// 	json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new Subject"})
+	// 	fmt.Println(err)
+	// 	return
+	// }
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "added new Subject"})
+	return
+}
+
+func ModuleApi(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+	showAPIRequest(r)
+	if r.Method == "POST" {
+		var newModule Professionalmodule
+		err := json.NewDecoder(r.Body).Decode(&newModule)
+		if err != nil {
+			json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new cycle"})
+			fmt.Println(err)
+			return
+		}
+		settings.DB.Create(&newModule)
+		json.NewEncoder(w).Encode(struct{ Result string }{Result: "added new cycle"})
+		return
+	}
+	path := replacePath(r.URL.Path, "/api/module/")
+	if r.Method == "GET" && path != "" {
+		num, err := strconv.Atoi(path)
+
+		if err != nil {
+			showError(r, err)
+			json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+			return
+		}
+
+		var output Professionalmodule
+		settings.DB.First(&output, num)
+		if output.ID == 0 {
+			json.NewEncoder(w).Encode(struct{ Error string }{Error: "error getting teacher"})
+			return
+		}
+		json.NewEncoder(w).Encode(output)
+		return
+	}
+
+	if r.Method == "GET" && path == "" {
+		var output []Professionalmodule
+		settings.DB.Find(&output)
+		json.NewEncoder(w).Encode(output)
+	}
+
+	if r.Method == "PATCH" || r.Method == "UPDATE" {
+		var module Professionalmodule
+		var moduleToUpdate Professionalmodule
+		err := json.NewDecoder(r.Body).Decode(&module)
+
+		if err != nil {
+			showError(r, err)
+			json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update module"})
+			return
+		}
+		settings.DB.First(&moduleToUpdate, module.ID)
+		settings.DB.Model(&moduleToUpdate).Updates(module)
+		json.NewEncoder(w).Encode(struct{ Result string }{Result: "updated module"})
+		return
+	}
+}
+
+func CycleApi(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+	showAPIRequest(r)
+	if r.Method == "POST" {
+		var newCycle Cycle
+		err := json.NewDecoder(r.Body).Decode(&newCycle)
+		if err != nil {
+			json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new cycle"})
+			fmt.Println(err)
+			return
+		}
+		settings.DB.Create(&newCycle)
+		json.NewEncoder(w).Encode(struct{ Result string }{Result: "added new cycle"})
+		return
+	}
+	path := replacePath(r.URL.Path, "/api/cycle/")
+	if r.Method == "GET" && path != "" {
+
+		num, err := strconv.Atoi(path)
+
+		if err != nil {
+			showError(r, err)
+			json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+			return
+		}
+
+		var output Cycle
+		settings.DB.First(&output, num)
+		if output.ID == 0 {
+			json.NewEncoder(w).Encode(struct{ Error string }{Error: "error getting teacher"})
+			return
+		}
+		json.NewEncoder(w).Encode(output)
+		return
+	}
+
+	if r.Method == "GET" && path == "" {
+		var output []Cycle
+		settings.DB.Find(&output)
+		json.NewEncoder(w).Encode(output)
+	}
+
+	if r.Method == "PATCH" || r.Method == "UPDATE" {
+		var cycle Cycle
+		var cycleToUpdate Cycle
+		err := json.NewDecoder(r.Body).Decode(&cycle)
+
+		if err != nil {
+			showError(r, err)
+			json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update cycle"})
+			return
+		}
+		settings.DB.First(&cycleToUpdate, cycle.ID)
+		settings.DB.Model(&cycleToUpdate).Updates(cycle)
+		json.NewEncoder(w).Encode(struct{ Result string }{Result: "updated cycle"})
+		return
+	}
+}
+
+func UpdateSubject(w http.ResponseWriter, r *http.Request) {
+	var subject Subject
+	var subjectToUpdate Subject
+	err := json.NewDecoder(r.Body).Decode(&subject)
+
+	if err != nil {
+		showError(r, err)
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update subject"})
+		return
+	}
+	settings.DB.First(&subjectToUpdate, subject.ID)
+	settings.DB.Model(&subjectToUpdate).Updates(subject)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "updated subject"})
+	return
+}
+
+func SubjectRoute(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+
+	showAPIRequest(r)
+
+	if r.Method == "POST" {
+		CreateSubject(w, r)
+		return
+	}
+
+	if r.Method == "UPDATE" || r.Method == "PATCH" {
+		UpdateSubject(w, r)
+		return
+	}
+
+	path := r.URL.Path
+
+	path = strings.Replace(path, "/api/subject/", "", 1)
+
+	if path == "" {
+		if r.Method == "GET" {
+			var output []Subject
+			settings.DB.Find(&output)
+			json.NewEncoder(w).Encode(output)
+		}
+		return
+	}
+
+	if path == "" && r.Method == "GET" {
+		GetSubjects(w, r)
+	}
+
+	if r.Method == "GET" {
+		GetSubject(w, r)
+		return
+	}
+
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "It is not GET method"})
+}
+
+func GetSubject(w http.ResponseWriter, r *http.Request) {
+	path := replacePath(r.URL.Path, "/api/subject/")
+	num, err := strconv.Atoi(path)
+
+	if err != nil {
+		showError(r, err)
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		return
+	}
+
+	var output Subject
+	settings.DB.First(&output, num)
+	if output.ID == 0 {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error getting subject"})
+		return
+	}
+	json.NewEncoder(w).Encode(output)
+	return
+}
+
+func GetSubjects(w http.ResponseWriter, r *http.Request) {
+	var output []Subject
+	settings.DB.Find(&output)
+	json.NewEncoder(w).Encode(output)
+}
+
+func GetSubjectByModule(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+	showAPIRequest(r)
+	if r.Method == "GET" {
+		path := r.URL.Path
+		path = strings.Replace(path, "/api/subject/module/", "", 1)
+		// num, err := strconv.Atoi(path)
+		// if err != nil || num < 0 || num > len(Subjects) {
+		// 	json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		// 	return
+		// }
+		var output []Subject
+		// for _, sub := range Subjects {
+		// 	if sub.IDprofessionalmodule == uint(num) {
+		// 		output = append(output, sub)
+		// 	}
+		// }
+		json.NewEncoder(w).Encode(output)
+	}
+}

+ 112 - 0
api/subjectOfGroup.go

@@ -0,0 +1,112 @@
+package api
+
+import (
+	"../settings"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+	"strings"
+)
+
+var SubjectOfGroups []Subjectofgroup
+
+func SubjectOfGroupRoute(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+
+	if r.Method == "POST" {
+		CreateSubjectOfGroup(w, r)
+		return
+	}
+
+	if r.Method == "UPDATE" || r.Method == "PATCH" {
+		UpdateSubjectOfGroup(w, r)
+		return
+	}
+
+	path := replacePath(r.URL.Path, "/api/groupsubject/")
+
+	if path == "" {
+		GetSubjectOfGroups(w, r)
+		return
+	}
+
+	if strings.Contains(path, "day/") {
+		GetSubjectByDay(w, r)
+		return
+	}
+
+	num, err := strconv.Atoi(path)
+
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Find(&SubjectOfGroups)
+	if num < 0 || num > len(SubjectOfGroups)+1 {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+
+	if r.Method == "GET" {
+		GetSubjectOfGroupById(w, r, num)
+		return
+	}
+
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "This method is not supported"})
+}
+
+func GetSubjectByDay(w http.ResponseWriter, r *http.Request) {
+	// var SubjectOfGroups []SubjectOfGroup
+	return
+}
+
+func UpdateSubjectOfGroup(w http.ResponseWriter, r *http.Request) {
+	var SubjectOfGroup Subjectofgroup
+	var SubjectOfGroupToUpdate Subjectofgroup
+	err := json.NewDecoder(r.Body).Decode(&SubjectOfGroup)
+
+	if err != nil {
+		showError(r, err)
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update subjectOfGroup"})
+		return
+	}
+	settings.DB.First(&SubjectOfGroupToUpdate, SubjectOfGroup.ID)
+	settings.DB.Model(&SubjectOfGroupToUpdate).Updates(SubjectOfGroup)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "updated subjectOfGroup"})
+	return
+}
+
+func CreateSubjectOfGroup(w http.ResponseWriter, r *http.Request) {
+	var newSubjectOfGroup Subjectofgroup
+	err := json.NewDecoder(r.Body).Decode(&newSubjectOfGroup)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new subjectOfGroup"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Create(&newSubjectOfGroup)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "added new s ubjectOfGroup"})
+	return
+}
+
+func GetSubjectOfGroupById(w http.ResponseWriter, r *http.Request, num int) {
+	var SubjectOfGroup Subjectofgroup
+	settings.DB.Where("id = ?", num).First(&SubjectOfGroup)
+	json.NewEncoder(w).Encode(SubjectOfGroup)
+	return
+}
+
+func GetSubjectOfGroups(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+	if r.Method == "GET" {
+		var SubjectOfGroups []Subjectofgroup
+		settings.DB.Find(&SubjectOfGroups)
+		json.NewEncoder(w).Encode(SubjectOfGroups)
+	}
+	return
+}

+ 106 - 0
api/subjectofplan.go

@@ -0,0 +1,106 @@
+package api
+
+import (
+	"../settings"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+)
+
+var subjectofplan []Subjectofplan
+
+func SubjectofplanRoute(w http.ResponseWriter, r *http.Request) {
+	
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+
+	
+	if r.Method == "POST" {
+		CreateSubjectofplan(w, r)
+		return
+	}
+
+	
+	if r.Method == "UPDATE" || r.Method == "PATCH" {
+		UpdateSubjectofplan(w, r)
+		return
+	}
+
+	
+	path := replacePath(r.URL.Path, "/api/subjectofplan/")
+
+	if path == "" {
+		GetSubjectofplan(w, r)
+		return
+	}
+	
+
+	num, err := strconv.Atoi(path)
+
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Find(&subjectofplan)
+	if num < 0 {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+
+	if r.Method == "GET" {
+		GetSubjectofplanById(w, r, num)
+		return
+	}
+
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "This method is not supported"})
+}
+
+func UpdateSubjectofplan(w http.ResponseWriter, r *http.Request) {
+	var subjectofplan Subjectofplan
+	var SubjectofplanToUpdate Subjectofplan
+	err := json.NewDecoder(r.Body).Decode(&subjectofplan)
+
+	if err != nil {
+		showError(r, err)
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update Subjectofplan"})
+		return
+	}
+	settings.DB.First(&SubjectofplanToUpdate, subjectofplan.ID)
+	settings.DB.Model(&SubjectofplanToUpdate).Updates(subjectofplan)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "updated Subjectofplan"})
+	return
+}
+
+func CreateSubjectofplan(w http.ResponseWriter, r *http.Request) {
+	var newSubjectofplan Subjectofplan
+	err := json.NewDecoder(r.Body).Decode(&newSubjectofplan)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new Subjectofplan"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Create(&newSubjectofplan)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "added new Subjectofplan"})
+	return
+}
+
+func GetSubjectofplanById(w http.ResponseWriter, r *http.Request, num int) {
+	var subjectofplan Subjectofplan
+	settings.DB.Where("id = ?", num).First(&subjectofplan)
+	json.NewEncoder(w).Encode(subjectofplan)
+	return
+}
+
+func GetSubjectofplan(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+	if r.Method == "GET" {
+		var subjectofplan []Subjectofplan
+		settings.DB.Find(&subjectofplan)
+		json.NewEncoder(w).Encode(subjectofplan)
+	}
+	return
+}

+ 106 - 0
api/subjecttype.go

@@ -0,0 +1,106 @@
+package api
+
+import (
+	"../settings"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+)
+
+var subjecttype []Subjecttype
+
+func SubjecttypeRoute(w http.ResponseWriter, r *http.Request) {
+	
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+
+	
+	if r.Method == "POST" {
+		CreateSubjecttype(w, r)
+		return
+	}
+
+	
+	if r.Method == "UPDATE" || r.Method == "PATCH" {
+		UpdateSubjecttype(w, r)
+		return
+	}
+
+	
+	path := replacePath(r.URL.Path, "/api/subjecttype/")
+
+	if path == "" {
+		GetSubjecttype(w, r)
+		return
+	}
+	
+
+	num, err := strconv.Atoi(path)
+
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Find(&ScheduleOfGroups)
+	if num < 0 || num > len(ScheduleOfGroups)+1 {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+
+	if r.Method == "GET" {
+		GetSubjecttypeById(w, r, num)
+		return
+	}
+
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "This method is not supported"})
+}
+
+func UpdateSubjecttype(w http.ResponseWriter, r *http.Request) {
+	var subjecttype Subjecttype
+	var SubjecttypeToUpdate Subjecttype
+	err := json.NewDecoder(r.Body).Decode(&subjecttype)
+
+	if err != nil {
+		showError(r, err)
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update subjecttype"})
+		return
+	}
+	settings.DB.First(&SubjecttypeToUpdate, subjecttype.ID)
+	settings.DB.Model(&SubjecttypeToUpdate).Updates(subjecttype)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "updated subjecttype"})
+	return
+}
+
+func CreateSubjecttype(w http.ResponseWriter, r *http.Request) {
+	var newSubjecttype Subjecttype
+	err := json.NewDecoder(r.Body).Decode(&newSubjecttype)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new Subjecttype"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Create(&newSubjecttype)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "added new Subjecttype"})
+	return
+}
+
+func GetSubjecttypeById(w http.ResponseWriter, r *http.Request, num int) {
+	var subjecttype Subjecttype
+	settings.DB.Where("id = ?", num).First(&subjecttype)
+	json.NewEncoder(w).Encode(subjecttype)
+	return
+}
+
+func GetSubjecttype(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+	if r.Method == "GET" {
+		var subjecttype []Subjecttype
+		settings.DB.Find(&subjecttype)
+		json.NewEncoder(w).Encode(subjecttype)
+	}
+	return
+}

+ 105 - 0
api/teacher.go

@@ -0,0 +1,105 @@
+package api
+
+import (
+	"fmt"
+	"encoding/json"
+	"net/http"
+	"strconv"
+	"strings"
+	"../settings"
+)
+
+var Teachers []Teacher
+
+func TeacherRoute(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+
+	if r.Method == "POST" {
+		CreateTeacher(w, r)
+		return
+	}
+
+	if r.Method == "UPDATE" || r.Method == "PATCH" {
+		UpdateTeacher(w, r)
+		return
+	}
+
+	path := r.URL.Path
+
+	path = strings.Replace(path, "/api/teacher/", "", 1)
+
+	if path==""{
+		GetTeachers(w, r)
+		return
+	}
+
+	num, err := strconv.Atoi(path)
+
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Find(&Teachers)
+	if num < 0 || num > len(Teachers)+1 {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "strconv error"})
+		fmt.Println(err)
+		return
+	}
+
+	if r.Method == "GET" {
+		//db.Where("name = ?", "jinzhu").First(&user)
+		GetTeacherById(w, r, num)
+		return
+	}
+
+	json.NewEncoder(w).Encode(struct{ Error string }{Error: "This method is not supported"})
+}
+
+func UpdateTeacher(w http.ResponseWriter, r *http.Request){
+		var teacher Teacher
+		var teacherToUpdate Teacher
+		err:= json.NewDecoder(r.Body).Decode(&teacher)
+
+		if err!=nil{
+			showError(r, err)
+			json.NewEncoder(w).Encode(struct{ Error string }{Error: "error update teacher"})
+			return
+		}
+		settings.DB.First(&teacherToUpdate, teacher.ID)
+		settings.DB.Model(&teacherToUpdate).Updates(teacher)
+		json.NewEncoder(w).Encode(struct{ Result string }{Result: "updated teacher"})
+		return
+}
+
+func CreateTeacher(w http.ResponseWriter, r *http.Request){
+	var newTeacher Teacher
+	err := json.NewDecoder(r.Body).Decode(&newTeacher)
+	if err != nil {
+		json.NewEncoder(w).Encode(struct{ Error string }{Error: "error add new teacher"})
+		fmt.Println(err)
+		return
+	}
+	settings.DB.Create(&newTeacher)
+	json.NewEncoder(w).Encode(struct{ Result string }{Result: "added new teacher"})
+	return
+}
+
+func GetTeacherById(w http.ResponseWriter, r *http.Request, num int){
+	var teacher Teacher
+	settings.DB.Where("id = ?", num).First(&teacher)
+	json.NewEncoder(w).Encode(teacher)
+	return
+}
+
+func GetTeachers(w http.ResponseWriter, r *http.Request) {
+	showAPIRequest(r)
+	w.Header().Set("Content-Type", "application/json")
+	if r.Method == "GET" {
+		var Teachers []Teacher
+		settings.DB.Find(&Teachers)
+		json.NewEncoder(w).Encode(Teachers)
+	}
+	return
+}

+ 90 - 0
api/token.go

@@ -0,0 +1,90 @@
+package api
+
+import(
+	"encoding/json"
+	"encoding/base64"
+	"crypto/rand"
+	"io/ioutil"
+	"strings"
+	"net/http"
+	"fmt"
+)
+
+type token struct{
+	Name string
+	Token string
+}
+
+var tokens []token
+
+func generateRandomBytes(max int) []byte {
+    var slice []byte = make([]byte, max)
+    _, err := rand.Read(slice)
+    if err != nil {
+        return nil
+    }
+    return slice
+}
+
+func base64Encode(data []byte) string {
+    return base64.StdEncoding.EncodeToString(data)
+}
+
+func GenerateNewToken(name string) string{
+	generated:=base64Encode(generateRandomBytes(10))
+	var newToken token = token{name, generated}
+	tokens = append(tokens, newToken)
+
+	writeTokensToFile()
+
+	return generated
+}
+
+func writeTokensToFile(){
+
+	tokens=getTokens()
+	jsonTokens, err:=json.Marshal(tokens)
+
+	if err!=nil{
+		printError(err)
+	}
+
+	err=ioutil.WriteFile("tokens.json", jsonTokens, 0644)
+
+	if err!=nil{
+		printError(err)
+	}
+	return
+}
+
+func getTokens() []token{
+	data, err := ioutil.ReadFile("tokens.json")
+	fmt.Println(string(data))
+	if err != nil{
+		printError(err)
+		return nil
+	}
+	var tokens []token
+	err = json.Unmarshal(data, &tokens)
+	if err!=nil{
+		printError(err)
+		return nil
+	}
+	return tokens
+}
+
+func CheckToken(r *http.Request) bool{
+	newToken := r.Header.Get("Authorization")
+	newToken = strings.Replace(newToken, "Bearer ", "", 1)
+
+	tokens=getTokens()
+	fmt.Println(tokens)
+	for _, check := range tokens{
+		if newToken==check.Token{
+			return true
+		}
+	}
+
+	return false
+}
+

+ 28 - 0
color/color.go

@@ -0,0 +1,28 @@
+package color
+
+import "runtime"
+
+var Reset   = "\033[0m"
+var Red     = "\033[31m"
+var Green   = "\033[32m"
+var Yellow  = "\033[33m"
+var Blue    = "\033[34m"
+var Purple  = "\033[35m"
+var Cyan    = "\033[36m"
+var Gray    = "\033[37m"
+var White   = "\033[97m"
+
+
+func init() {
+	if runtime.GOOS == "windows" {
+		Reset   = ""
+		Red     = ""
+		Green   = ""
+		Yellow  = ""
+		Blue    = ""
+		Purple  = ""
+		Cyan    = ""
+		Gray    = ""
+		White   = ""
+	}
+}

+ 11 - 0
html/404.html

@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<title>404 Not Found</title>
+		<meta charset="UTF-8">
+	</head>
+
+	<body>
+		<p>404 not found</p>
+	</body>
+</html>

+ 114 - 0
html/api.html

@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <title>API</title>
+
+        <!-- META SECTION -->
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
+        <meta name="viewport" content="width=device-width, initial-scale=1">
+
+        <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
+        <link rel="icon" href="favicon.ico" type="image/x-icon">
+        <!-- END META SECTION -->
+        <!-- CSS INCLUDE -->
+        <link rel="stylesheet" href="../static/css/styles.css">
+        <!-- EOF CSS INCLUDE -->
+    </head>
+    <body>
+        <!-- APP WRAPPER -->
+        <div class="app">
+            <!-- START APP CONTAINER -->
+            <div class="app-container">
+                <!-- START SIDEBAR -->
+                <!-- END SIDEBAR -->
+                <!-- START APP CONTENT -->
+                <div class="app-content">
+                    <!-- START PAGE CONTAINER -->
+                    <div class="container">
+                        <button type="button" class="btn btn-primary btn-glow margin-right-5 margin-bottom-20" onclick="window.location.href = /plan/">Назад</button>
+                        <table class="table-bordered table table-responsive" style="width: 100%; font-size:150%">
+                          <tr>
+                            <td><a href="/api/teacher/">/api/teacher/</a></td>
+                            <td>Get teacher by ID (fe: /api/teacher/1). Can be POST, GET, UPDATE (PATCH)</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/teacher">/api/teacher</a></td>
+                            <td>Get list of all teachers</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/classroom/">/api/classroom/</a></td>
+                            <td>Get classroom by ID (fe: /api/classroom/1). Can be POST, GET, UPDATE (PATCH)</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/classroom">/api/classroom</a></td>
+                            <td>Get list of all classrooms</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/classroom/computer">/api/classroom/computer</a></td>
+                            <td>Get list of all computer classrooms</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/classroom/lecture">/api/classroom/lecture</a></td>
+                            <td>Get list of all lecture classrooms</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/group">/api/group</a></td>
+                            <td>Get list of all groups</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/group/">/api/group/</a></td>
+                            <td>Get group by ID (fe: /api/group/471). Can be POST, GET, UPDATE (PATCH)</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/group/specialty/">/api/group/specialty/</a></td>
+                            <td>Get group by specialty (fe: /api/group/specialty/1). Can be POST, GET, UPDATE (PATCH)</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/schedule/generate">/api/schedule/generate</a></td>
+                            <td>Get schedule that generates when method called</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/subject">/api/subject</a></td>
+                            <td>Get list of all subjects</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/subject/module/">/api/subject/module/</a></td>
+                            <td>Get subject by professional module</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/subject/">/api/subject/</a></td>
+                            <td>Get subject by ID (fe: /api/subject/1). Can be POST, GET, UPDATE (PATCH)</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/building/">/api/building/</a></td>
+                            <td>Get list of buildings or building by ID (/api/building/{ID})</td>
+                          </tr>
+                          <tr>
+                            <td><a href="/api/modelsDownload">Download</a></td>
+                            <td>Models file</td>
+                          </tr>
+                        </table>
+                    </div>
+                    <!-- END PAGE CONTAINER -->
+                </div>
+                <!-- END APP CONTENT -->
+            </div>
+            <!-- END APP CONTAINER -->
+        </div>
+        <!-- END APP WRAPPER -->
+
+        <!-- IMPORTANT SCRIPTS -->
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-migrate.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-ui.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/bootstrap/bootstrap.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/moment/moment.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/customscrollbar/jquery.mCustomScrollbar.min.js"></script>
+        <!-- END IMPORTANT SCRIPTS -->
+        <!-- APP SCRIPTS -->
+        <script type="text/javascript" src="../static/js/app.js"></script>
+        <script type="text/javascript" src="../static/js/app_plugins.js"></script>
+        <!-- END APP SCRIPTS -->
+    </body>
+</html>

+ 347 - 0
html/bellschedule.html

@@ -0,0 +1,347 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <title>Распределение нагрузки преподавателей</title>
+        {{ template "head_tmpl" }}
+    </head>
+    <body>
+
+        <!-- APP WRAPPER -->
+        <div class="app">
+
+            <!-- START APP CONTAINER -->
+            <div class="app-container">
+                <!-- START SIDEBAR -->
+                <div class="app-sidebar app-navigation app-navigation-fixed scroll app-navigation-style-default dir-left">
+                    {{ template "navbar" }}
+                </div>
+                <!-- END SIDEBAR -->
+
+                <!-- START APP CONTENT -->
+                <div class="app-content">
+                    <!-- START APP HEADER -->
+                    <div class="app-header app-header-design-default">
+                        <ul class="app-header-buttons">
+                            <li class="visible-mobile"><a href="#" class="btn btn-link btn-icon" data-sidebar-toggle=".app-sidebar.dir-left"><span class="icon-menu"></span></a></li>
+                            <li class="hidden-mobile"><a href="#" class="btn btn-link btn-icon" data-sidebar-minimize=".app-sidebar.dir-left"><span class="icon-menu"></span></a></li>
+                        </ul>
+                    <!-- END APP HEADER  -->
+
+                    <!-- START PAGE HEADING -->
+                    <div class="app-heading app-heading-bordered app-heading-page">
+                        <div class="title">
+                            <h2>Распределение нагрузки преподавателей</h2>
+                            <p>Здесь можно создать новый учебный план</p>
+                        </div>
+                        <!--
+                        <div class="heading-elements">
+                            <a href="#" class="btn btn-danger" id="page-like"><span class="app-spinner loading"></span> loading...</a>
+                            <a href="https://themeforest.net/item/boooya-revolution-admin-template/17227946?ref=aqvatarius&license=regular&open_purchase_for_item_id=17227946" class="btn btn-success btn-icon-fixed"><span class="icon-text">$24</span> Purchase</a>
+                        </div>
+                        -->
+                    </div>
+                    <div class="app-heading-container app-heading-bordered bottom">
+                        <ul class="breadcrumb">
+                           <!--  <li><a href="#">Dashboard</a></li>
+                            <li><a href="#">Layouts</a></li>
+                            <li class="active">Fixed Navigation</li> -->
+                        </ul>
+                    </div>
+                    <!-- END PAGE HEADING -->
+
+                    <!-- START PAGE CONTAINER -->
+                    <div class="container">
+                        <!-- END BLOCk -->
+                        <div class="block">
+                        <div class="table-responsive">
+                            <h1>Расписание звонков учебных занятий</h1>
+                                    <table class="table table-hover table-bordered">
+                                        <tr>
+                                            <th>№ пары</th>
+                                            <th>Урок</th>
+                                            <th>Начало</th>
+                                            <th>Конец</th>
+                                            <th>№ пары</th>
+                                        </tr>
+                                        <tr>
+                                            <td rowspan="2">1</td>
+                                            <td>1</td>
+                                            <td>8:30</td>
+                                            <td>9:15</td>
+                                            <td rowspan="2">1</td>
+                                        </tr>
+                                        <tr>
+                                            <td>2</td>
+                                            <td>9:20</td>
+                                            <td>10:05</td>
+                                        </tr>
+                                        <tr>
+                                            <td rowspan="2">2</td>
+                                            <td>1</td>
+                                            <td>10:15</td>
+                                            <td>11:00</td>
+                                            <td rowspan="2">2</td>
+                                        </tr>
+                                        <tr>
+                                            <td>2</td>
+                                            <td>11:05</td>
+                                            <td>11:50</td>
+                                        </tr>
+                                        <tr>
+                                            <th colspan="5">Обед 11:30 - 12:30</th>
+                                        </tr>
+                                        <tr>
+                                            <td rowspan="2">3</td>
+                                            <td>1</td>
+                                            <td>12:30</td>
+                                            <td>13:15</td>
+                                            <td rowspan="2">3</td>
+                                        </tr>
+                                        <tr>
+                                            <td>2</td>
+                                            <td>13:20</td>
+                                            <td>14:05</td>
+                                        </tr>
+                                        <tr>
+                                            <td rowspan="2">4</td>
+                                            <td>1</td>
+                                            <td>14:15</td>
+                                            <td>15:00</td>
+                                            <td rowspan="2">4</td>
+                                        </tr>
+                                        <tr>
+                                            <td>2</td>
+                                            <td>15:05</td>
+                                            <td>15:50</td>
+                                        </tr>
+                                        <tr>
+                                            <th colspan="5">перерыв 20 минут</th>
+                                        </tr>
+                                        <tr>
+                                            <td rowspan="2">5</td>
+                                            <td>1</td>
+                                            <td>16:10</td>
+                                            <td>16:55</td>
+                                            <td rowspan="2">5</td>
+                                        </tr>
+                                        <tr>
+                                            <td>2</td>
+                                            <td>17:00</td>
+                                            <td>17:45</td>
+                                        </tr>
+                                        <tr>
+                                            <td rowspan="2">6</td>
+                                            <td>1</td>
+                                            <td>17:55</td>
+                                            <td>18:40</td>
+                                            <td rowspan="2">6</td>
+                                        </tr>
+                                        <tr>
+                                            <td>2</td>
+                                            <td>18:45</td>
+                                            <td>19:30</td>
+                                        </tr>
+                                        <tr>
+                                            <td rowspan="2">7</td>
+                                            <td>1</td>
+                                            <td>19:40</td>
+                                            <td>20:25</td>
+                                            <td rowspan="2">7</td>
+                                        </tr>
+                                        <tr>
+                                            <td>2</td>
+                                            <td>20:30</td>
+                                            <td>21:15</td>
+                                        </tr>
+                                    </table>
+                                        <h1>Расписание звонков учебных занятий в среду и субботу</h1>
+
+                                        <table class="table table-bordered table-hover">
+
+                                        <thead>
+
+                                            <tr>
+
+                                                <th>№ пары</th>
+
+                                                <th>Начало</th>
+
+                                                <th>Конец</th>
+
+                                                <th>№ пары</th>
+
+                                            </tr>
+
+                                        </thead>
+
+                                        <tbody>
+
+                                            <tr>
+
+                                                <td>1</td>
+
+                                                <td>8:30</td>
+
+                                                <td>9:30</td>
+
+                                                <td>1</td>
+
+                                            </tr>
+
+                                            <tr>
+
+                                                <td>2</td>
+
+                                                <td>9:40</td>
+
+                                                <td>10:40</td>
+
+                                                <td>2</td>
+
+                                            </tr>
+
+                                            <tr>
+
+                                                <td>3</td>
+
+                                                <td>10:50</td>
+
+                                                <td>11:50</td>
+
+                                                <td>3</td>
+
+                                            </tr>
+
+                                            <tr>
+
+                                                <td>4</td>
+
+                                                <td>12:00</td>
+
+                                                <td>13:00</td>
+
+                                                <td>4</td>
+
+                                            </tr>
+
+                                            <tr>
+
+                                                <td>5</td>
+
+                                                <td>13:10</td>
+
+                                                <td>14:10</td>
+
+                                                <td>5</td>
+
+                                            </tr>
+
+                                            <tr>
+
+                                                <td>6</td>
+
+                                                <td>14:20</td>
+
+                                                <td>15:20</td>
+
+                                                <td>6</td>
+
+                                            </tr>
+
+                                            <tr>
+
+                                                <td>7</td>
+
+                                                <td>15:30</td>
+
+                                                <td>16:30</td>
+
+                                                <td>7</td>
+
+                                            </tr>
+
+                                            <tr>
+
+                                                <td>8</td>
+
+                                                <td>16:40</td>
+
+                                                <td>17:40</td>
+
+                                                <td>8</td>
+
+                                            </tr>
+
+                                            <tr>
+
+                                                <td>9</td>
+
+                                                <td>17:50</td>
+
+                                                <td>18:50</td>
+
+                                                <td>9</td>
+
+                                            </tr>
+
+                                            <tr>
+
+                                                <td>10</td>
+
+                                                <td>19:00</td>
+
+                                                <td>20:00</td>
+
+                                                <td>10</td>
+
+                                            </tr>
+
+                                            <tr>
+
+                                                <td>11</td>
+
+                                                <td>20:10</td>
+
+                                                <td>21:10</td>
+
+                                                <td>11</td>
+
+                                            </tr>
+
+                                        </tbody>
+
+                        </table>
+                        </div>
+                        </div>
+                    </div>
+                    <!-- END PAGE CONTAINER -->
+
+                </div>
+                <!-- END APP CONTENT -->
+
+            </div>
+            <!-- END APP CONTAINER -->
+
+        </div>
+
+        <!-- IMPORTANT SCRIPTS -->
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-migrate.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-ui.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/bootstrap/bootstrap.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/moment/moment.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/customscrollbar/jquery.mCustomScrollbar.min.js"></script>
+        <!-- END IMPORTANT SCRIPTS -->
+        <script type="text/javascript" src="../static/js/vendor/bootstrap-select/bootstrap-select.js"></script>
+
+        <script type="text/javascript" src="../static/js/vendor/select2/select2.full.min.js"></script>
+        <!-- APP SCRIPTS -->
+        <script type="text/javascript" src="../static/js/app.js"></script>
+        <script type="text/javascript" src="../static/js/app_plugins.js"></script>
+        <style>
+
+
+</style>
+        <!-- END APP SCRIPTS -->
+    </body>
+</html>

+ 155 - 0
html/classroom.html

@@ -0,0 +1,155 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        {{ template "head_tmpl" }}
+    </head>
+    <body>
+        <!-- APP WRAPPER -->
+        <div class="app">
+            <!-- START APP CONTAINER -->
+            <div class="app-container">
+                <!-- START SIDEBAR -->
+                <div class="app-sidebar app-navigation app-navigation-fixed scroll app-navigation-style-default dir-left">
+                    {{ template "navbar" }}
+                </div>
+                <!-- END SIDEBAR -->
+                <!-- START APP CONTENT -->
+                <div class="app-content">
+                    <!-- START APP HEADER -->
+                    <div class="app-header app-header-design-default">
+                        <ul class="app-header-buttons">
+                            <li class="visible-mobile"><a href="#" class="btn btn-link btn-icon"
+                                data-sidebar-toggle=".app-sidebar.dir-left"><span
+                                class="icon-menu"></span></a></li>
+                                <li class="hidden-mobile"><a href="#" class="btn btn-link btn-icon"
+                                    data-sidebar-minimize=".app-sidebar.dir-left"><span
+                                    class="icon-menu"></span></a></li>
+                                </ul>
+                                <!-- END APP HEADER  -->
+                                <!-- START PAGE HEADING -->
+                                <div class="app-heading app-heading-bordered app-heading-page">
+                                    <div class="title">
+                                        <h2>Информация о кабинетах</h2>
+                                        <p>Здесь можно редактировать информацию о кабинетах </p>
+                                    </div>
+                                </div>
+                                <!-- END PAGE HEADING -->
+                                <!-- START PAGE CONTAINER -->
+                                <div class="container" id="app">
+                                        <!-- START BLOCk -->
+                                        <div class="block">
+                                            <div class="row" >
+                                                <div class="col-md-4">
+                                                    <button type="button" class="btn btn-success btn-lg" data-toggle="modal" data-target="#modal-default">Добавить</button>
+                                                </div>
+                                                <div class="col-md-4" >
+                                                    <button type="button" class="btn btn-danger btn-lg"  >Удалить</button>
+                                                </div>
+                                                <div class="col-md-4">
+                                                    <button type="button" class="btn btn-warning btn-lg">Редактировать</button>
+                                                </div>
+                                            </div>
+                                            <br>
+                                            <table class="table table-striped table-bordered ">
+                                                <tr>
+                                                    <th>Номер кабинета</th>
+                                                    <th>Количество мест</th>
+                                                    <th>Тип кабинета</th>
+                                                    <th>Корпус</th>
+                                                </tr>
+                                                <tr v-for="(c, i) in classrooms">
+                                                    <td>${c.Name}</td>
+                                                    <td>${c.Placequantity}</td>
+                                                    <td>${c.Iscomputer ? "Компьютерный" : "Лекционный"}</td>
+                                                    <td v-if="c.IDBuilding === 1">Герцена, 18</td>
+                                                    <td v-if="c.IDBuilding === 2">Московский тракт, 12</td>
+                                                 </tr>
+<!--                                                 <tr>
+                                                    <td><a href="#" id="classroomId" data-type="text" data-pk="1" data-title="Номер кабинета" class="editable editable-click" data-original-title="" title="">{{ .ClassroomId}}</a></td>
+                                                    <td><a href="#" id="placeQuantity" data-type="text" data-pk="1" data-title="Номер кабинета" class="editable editable-click" data-original-title="" title="">{{ .PlaceQuantity}}</a></td>
+                                                    <td><a href="#" id="IsComputer" data-type="text" data-pk="1" data-title="Номер кабинета" class="editable editable-click" data-original-title="" title="">{{ .IsComputer}}</a></td>
+                                                    <td><a href="#" id="IDBuilding" data-type="text" data-pk="1" data-title="Номер кабинета" class="editable editable-click" data-original-title="" title="">{{ .IDBuilding}}</a></td>
+                                                </tr> -->
+                                            </table>
+                                        </div>
+                                    </div>
+                                </div>
+                                <!-- END BLOCk -->
+                            </div>
+                            <!-- END PAGE CONTAINER -->
+                        </div>
+                        <!-- END APP CONTENT -->
+                        <div class="modal fade" id="modal-default" tabindex="-1" role="dialog" aria-labelledby="modal-default-header">
+                            <div class="modal-dialog modal-lg" role="document">
+                                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true" class="icon-cross"></span></button>
+                                <div class="modal-content">
+                                    <div class="block">
+                                        <div class="modal-header">
+                                            <h4 class="modal-title" id="modal-default-header">Добавление кабинета</h4>    
+                                        </div>
+                                        <div class="form-group">
+                                            <div class="col-md-3">
+                                                <label>Номер кабинета</label>
+                                            </div>
+                                            <div class="col-md-9">
+                                                <input type="text" class="form-control numberCab">
+                                            </div>
+                                        </div>
+                                        <div class="form-group">
+                                            <label class="control-label col-md-3">Количество мест</label>
+                                            <div class="col-md-9">
+                                                <input type="text" class="form-control placeQuantity">
+                                            </div>
+                                        </div>
+                                        <div class="form-group">
+                                            <label class="control-label col-md-3">Корпус</label>
+                                            <div class="col-md-9">
+                                                <div class="app-radio inline">
+                                                    <label><input type="radio" class="building-radio" name="app-radio-2" value="1" checked="checked"> ГК</label>
+                                                </div>
+                                                <div class="app-radio inline">
+                                                    <label><input type="radio" class="building-radio" name="app-radio-2" value="2"> ЦОПП</label>
+                                                </div>
+                                            </div>
+                                            <div class="form-group">
+                                                <div class="col-md-6">
+                                                    <div class="app-checkbox inline">
+                                                        <label><input type="checkbox" class="computerclass" name="app-checkbox-2" value="0" checked="checked"> Компьютерный</label>
+                                                    </div>
+                                                </div>
+                                            </div>
+                                            
+                                            <div class="modal-footer">
+                                                <button type="button" class="btn btn-link" data-dismiss="modal">Закрыть</button>
+                                                <button type="button" class="btn btn-default" onclick="addClassroom()">Добавить</button>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <!-- END APP CONTAINER -->
+                    </div>
+                    <script src="https://unpkg.com/vue"></script>
+                    <
+                    <!-- IMPORTANT SCRIPTS -->
+                    <script type="text/javascript" src="../static/js/api/vueClassrooms.js"></script>
+                    <script type="text/javascript" src="../static/js/api/jsClassrooms.js"></script>
+                    <script type="text/javascript" src="../static/js/vendor/jquery/jquery.min.js"></script>
+                    <script type="text/javascript" src="../static/js/vendor/jquery/jquery-migrate.min.js"></script>
+                    <script type="text/javascript" src="../static/js/vendor/jquery/jquery-ui.min.js"></script>
+                    <script type="text/javascript" src="../static/js/vendor/bootstrap/bootstrap.min.js"></script>
+                    <script type="text/javascript" src="../static/js/vendor/moment/moment.min.js"></script>
+                    <script type="text/javascript" src="../static/js/vendor/customscrollbar/jquery.mCustomScrollbar.min.js"></script>
+                    <!-- END IMPORTANT SCRIPTS -->
+                    <script type="text/javascript" src="../static/js/vendor/bootstrap-select/bootstrap-select.js"></script>
+                    <script type="text/javascript" src="../static/js/vendor/select2/select2.full.min.js"></script>
+                    <!-- APP SCRIPTS -->
+                    <script type="text/javascript" src="../static/js/app.js"></script>
+                    <script src="../static/js/vendor/xeditable/bootstrap-editable.min.js"></script>
+                    <script src="../static/js/vendor/xeditable/ext/address.js"></script>
+                    <script type="text/javascript" src="../static/js/app_plugins.js"></script>
+                    <!-- END APP SCRIPTS -->
+                    <script src="../static/js/app_demo_editable.js"></script>
+                </body>
+            </html>

+ 142 - 0
html/cycle.html

@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        {{ template "head_tmpl" }}
+    </head>
+    <body>
+
+        <!-- APP WRAPPER -->
+        <div class="app">
+
+            <!-- START APP CONTAINER -->
+            <div class="app-container">
+                <!-- START SIDEBAR -->
+                <div class="app-sidebar app-navigation app-navigation-fixed scroll app-navigation-style-default dir-left">
+                    {{ template "navbar" }}
+                </div>
+                <!-- END SIDEBAR -->
+
+                <!-- START APP CONTENT -->
+                <div class="app-content app-sidebar-left">
+                    <!-- START APP HEADER -->
+                    <div class="app-header app-header-design-default">
+                        <ul class="app-header-buttons">
+                            <li class="visible-mobile"><a href="#" class="btn btn-link btn-icon" data-sidebar-toggle=".app-sidebar.dir-left"><span class="icon-menu"></span></a></li>
+                            <li class="hidden-mobile"><a href="#" class="btn btn-link btn-icon" data-sidebar-minimize=".app-sidebar.dir-left"><span class="icon-menu"></span></a></li>
+                        </ul>
+                    </div>
+                    <!-- END APP HEADER  -->
+
+                    <!-- START PAGE CONTAINER -->
+                    <div class="container" id="content">
+                        <div class="col-md-5">
+                            <button type="button" class="btn btn-success">Добавить цикл</button>
+                            <button type="button" class="btn btn-danger">Удалить цикл</button>
+                            <div>
+                                <div class="margin-top-20">
+                                    <label>Выберите цикл</label>
+                                    <select class="s2-select- form-control" id="moduleList">
+                                        <option>Lorem ipsum dolor</option>
+                                        <option>Sit ament nopilous</option>
+                                        <option>Toi samo tuda</option>
+                                        <option>Mauris dolor nulla</option>
+                                        <option>Phasellus tincidunt</option>
+                                    </select>
+                                    <label class="control-label margin-top-50">Название цикла</label>
+                                    <div class="col-md-40">
+                                        <input type="text" v-model="fullNameCycle" v-on:keyup="getShortNameCycle" class="form-control" value="Lorem ipsum">
+                                    </div>
+                                    <label class="control-label margin-top-50">Сокращённое наименование</label>
+                                    <div class="col-md-40">
+                                        <input type="text" v-model="shortNameCycle" class="form-control" value="Lorem ipsum">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="col-md-5 margin-left-50">
+                            <button type="button" class="btn btn-success">Добавить модуль</button>
+                            <button type="button" class="btn btn-danger">Удалить модуль</button>
+                            <div>
+                                <div class="margin-top-20">
+                                    <label>Выберите Модуль</label>
+                                    <select class="s2-select- form-control" id="moduleList">
+                                        <option>Lorem ipsum dolor</option>
+                                        <option>Sit ament nopilous</option>
+                                        <option>Toi samo tuda</option>
+                                        <option>Mauris dolor nulla</option>
+                                        <option>Phasellus tincidunt</option>
+                                    </select>
+                                    <label class="control-label margin-top-50">Название цикла</label>
+                                    <div class="col-md-40">
+                                        <input type="text" v-model="fullNameModule" v-on:keyup="getShortNameModule" class="form-control" value="Lorem ipsum">
+                                    </div>
+                                    <label class="control-label margin-top-50">Сокращённое наименование</label>
+                                    <div class="col-md-40">
+                                        <input type="text" v-model="shortNameModule" class="form-control" value="Lorem ipsum">
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+
+                    </div>
+                    <!-- END PAGE CONTAINER -->
+
+                </div>
+                <!-- END APP CONTENT -->
+
+            </div>
+            <!-- END APP CONTAINER -->
+
+            <!-- START APP SIDEPANEL -->
+            <div class="app-sidepanel scroll" data-overlay="show">
+                <div class="container">
+
+
+
+                </div>
+            </div>
+            <!-- END APP SIDEPANEL -->
+
+            <!-- APP OVERLAY -->
+            <div class="app-overlay"></div>
+            <!-- END APP OVERLAY -->
+        </div>
+        <!-- END APP WRAPPER -->
+
+        <!-- IMPORTANT SCRIPTS -->
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-migrate.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-ui.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/bootstrap/bootstrap.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/moment/moment.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/customscrollbar/jquery.mCustomScrollbar.min.js"></script>
+        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
+        <script type="text/javascript">
+        const vueApp = new Vue({
+        delimiters: ['${', '}'],
+        el: "#content",
+        data:{
+        fullNameModule: null,
+        shortNameModule: null,
+        fullNameCycle: null,
+        shortNameCycle: null,
+        },
+        methods:{
+        getShortNameCycle(){
+        var matches = this.fullNameCycle.match(/\b(\w)/g); // ['J','S','O','N']
+        this.shortNameCycle = matches.join(''); // JSON
+        },
+        getShortNameModule(){
+        var matches = this.fullNameModule.match(/\b(\w)/g); // ['J','S','O','N']
+        this.shortNameModule = matches.join(''); // JSON
+        },
+        },
+        })
+        </script>
+        <!-- END IMPORTANT SCRIPTS -->
+        <!-- APP SCRIPTS -->
+        <script type="text/javascript" src="../static/js/app.js"></script>
+        <script type="text/javascript" src="../static/js/app_plugins.js"></script>
+        <!-- END APP SCRIPTS -->
+    </body>
+</html>

+ 175 - 0
html/group.html

@@ -0,0 +1,175 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <head>
+            {{ template "head_tmpl" }}
+        </head>
+    </head>
+    <body>
+
+        <!-- APP WRAPPER -->
+        <div class="app">
+            <!-- START APP CONTAINER -->
+            <div class="app-container">
+                <!-- START SIDEBAR -->
+                <div class="app-sidebar app-navigation app-navigation-fixed scroll app-navigation-style-default dir-left">
+                    {{ template "navbar" }}
+                </div>
+                <!-- END SIDEBAR -->
+
+                <!-- START APP CONTENT -->
+                <div class="app-content">
+                    <!-- START APP HEADER -->
+                    <div class="app-header app-header-design-default">
+                        <ul class="app-header-buttons">
+                            <li class="visible-mobile"><a href="#" class="btn btn-link btn-icon" data-sidebar-toggle=".app-sidebar.dir-left"><span class="icon-menu"></span></a></li>
+                            <li class="hidden-mobile"><a href="#" class="btn btn-link btn-icon" data-sidebar-minimize=".app-sidebar.dir-left"><span class="icon-menu"></span></a></li>
+                        </ul>
+                        <!-- END APP HEADER  -->
+
+                        <!-- START PAGE HEADING -->
+                        <div class="app-heading app-heading-bordered app-heading-page">
+                            <div class="title">
+                                <h2>Распределение нагрузки преподавателей</h2>
+                                <p>Здесь можно создать новый учебный план</p>
+                            </div>
+                        </div>
+                        <!-- END PAGE HEADING -->
+
+                        <!-- START PAGE CONTAINER -->
+                        <div class="container" id="app">
+                            <div class="block">
+                                <div class="col-md-4 col-ms-4 grid-element filter-business">
+                                    <div class="tile-basic">
+                                        <a href="#" class="preview" data-preview-size="modal-lg">
+                                            <div class="tile-content tile-content-condensed-bottom text-center">
+                                                <button type="button" class="btn btn-success btn-lg">Добавить</button>
+                                            </a>
+                                        </div>
+                                    </div>
+                                </div>
+                                <div class="col-md-4 col-ms-4 grid-element filter-business">
+                                    <div class="tile-basic">
+                                        <a href="#" class="preview" data-preview-size="modal-lg">
+                                            <div class="tile-content tile-content-condensed-bottom text-center">
+                                                <button type="button" class="btn btn-warning btn-lg">Редактировать</button>
+                                            </a>
+                                        </div>
+                                    </div>
+                                </div>
+                                <div class="col-md-4 col-ms-4 grid-element filter-business">
+                                    <div class="tile-basic">
+                                        <a href="#" class="preview-delete" data-preview-size="modal-lg">
+                                            <div class="tile-content tile-content-condensed-bottom text-center">
+                                                <button type="button" class="btn btn-danger btn-lg">Удалить</button>
+                                            </div>
+                                        </a>
+                                    </div>
+                                </div>
+                                <div class="block-content">
+                            <table class="table table-striped table-bordered">
+                                <h1>Группы</h1>
+                                <p>Здесь вы можете добавить, удалить или редактировать группы.</p>
+                                <thead>
+                                    <tr>
+                                        <th>Группа</th>
+                                        <th>Специальность</th>
+                                        <th>Куратор</th>
+                                        <th>Курс</th>
+                                    </tr>
+                                </thead>
+                                <tbody>
+                                    <tr v-for="c in groups">
+                                        <td>${c.Groupnumber}</td>
+                                        <td>${c.IDSpecialty}</td>
+                                        <td>${c.IDTeacher}</td>
+                                        <td>${c.Year}</td>
+                                    </tr>
+                                </tbody>
+                            </table>
+                        </div>
+                            </div>
+                            <!-- END PAGE CONTAINER -->
+
+                        </div>
+                        <!-- END APP CONTENT -->
+
+                    </div>
+                    <!-- END APP CONTAINER -->
+
+                </div>
+                <!-- модальные окна -->
+                        <div class="modal fade" id="preview" tabindex="-1" role="dialog">
+                            <div class="modal-dialog">
+                                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true" class="icon-cross"></span></button>
+                                <div class="modal-content">
+                                    <div class="block">
+                                        <div class="row">
+                                    <div class="col-md-12">
+                                        <label>Номер группы</label>
+                                        <div class="input-group">
+                                            <input type="text" class="form-control" placeholder="362">
+                                        </div>
+                                    </div>
+                                    <div class="col-md-12">
+                                        <label>Специальность</label>
+                                        <select class="bs-select">
+                                            <option>00.00.00 Программирование</option>
+                                            <option>11.11.11 Администрирование</option>
+                                            <option>22.22.22 Монтажники</option>
+                                            <option>33.33.33 Пример</option>
+                                            <option>44.44.44 Пример</option>
+                                        </select>
+                                    </div>
+                                    <div class="col-md-12">
+                                        <label>Куратор</label>
+                                        <select>
+                                            <option v-for="t in teachers" v-bind:value="t.Surname">${t.Surname}</option>
+                                        </select>
+                                    </div>
+                                    <div class="col-md-12">
+                                        <label>Год приёма</label>
+                                        <select class="bs-select">
+                                            <option>2016</option>
+                                            <option>2017</option>
+                                            <option>2018</option>
+                                            <option>2019</option>
+                                        </select>
+                                    </div>
+                                    <div class="col-md-12">
+                                        <label>Год приёма</label>
+                                        <select class="bs-select">
+                                            <option>2020</option>
+                                            <option>2021</option>
+                                            <option>2022</option>
+                                            <option>2023</option>
+                                        </select>
+                                    </div>
+                                        <div class="col-md-12">
+                                            <br>
+                                            <button type="button" class="btn btn-default" onclick="addSubject()">Добавить модуль</button>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <!-- модальные окна -->
+                <script src="https://unpkg.com/vue"></script>
+                <script type="text/javascript" src="../static/js/api/vueGroup.js"></script>
+                <!-- IMPORTANT SCRIPTS -->
+                <script type="text/javascript" src="../static/js/vendor/jquery/jquery.min.js"></script>
+                <script type="text/javascript" src="../static/js/vendor/jquery/jquery-migrate.min.js"></script>
+                <script type="text/javascript" src="../static/js/vendor/jquery/jquery-ui.min.js"></script>
+                <script type="text/javascript" src="../static/js/vendor/bootstrap/bootstrap.min.js"></script>
+                <script type="text/javascript" src="../static/js/vendor/moment/moment.min.js"></script>
+                <script type="text/javascript" src="../static/js/vendor/customscrollbar/jquery.mCustomScrollbar.min.js"></script>
+                <!-- END IMPORTANT SCRIPTS -->
+                <script type="text/javascript" src="../static/js/vendor/bootstrap-select/bootstrap-select.js"></script>
+                <script type="text/javascript" src="../static/js/vendor/select2/select2.full.min.js"></script>
+                <!-- APP SCRIPTS -->
+                <script type="text/javascript" src="../static/js/app.js"></script>
+                <script type="text/javascript" src="../static/js/app_plugins.js"></script>
+                <script type="text/javascript" src="../static/js/app_demo.js"></script>
+                <!-- END APP SCRIPTS -->
+            </body>
+        </html>

文件差異過大導致無法顯示
+ 335 - 0
html/groupcard.html


+ 15 - 0
html/head.html

@@ -0,0 +1,15 @@
+{{ define "head_tmpl" }}
+        <title>Учебная часть</title>
+
+        <!-- META SECTION -->
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
+        <meta name="viewport" content="width=device-width, initial-scale=1">
+
+        <link rel="shortcut icon" href="../static/img/icons/logo.ico" type="image/x-icon">
+        <link rel="icon" href="../static/img/icons/logo.ico" type="image/x-icon">
+        <!-- END META SECTION -->
+        <!-- CSS INCLUDE -->
+        <link rel="stylesheet" href="../static/css/styles.css">
+        <!-- EOF CSS INCLUDE -->
+{{ end }}

文件差異過大導致無法顯示
+ 352 - 0
html/index.html


+ 94 - 0
html/log in.html

@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>                                   
+        {{ template "head_tmpl" }}
+    </head>
+    <body>        
+        
+        <!-- APP WRAPPER -->
+        <div class="app">
+
+            <!-- START APP CONTAINER -->
+            <div class="app-container">
+                
+                <div class="app-login-box">                                        
+                    <div class="app-login-box-user"><img src="img/user/no-image.png" alt="John Doe"></div>
+                    <div class="app-login-box-title">
+                        <div class="title">Already a member?</div>
+                        <div class="subtitle">Sign in to your account</div>                        
+                    </div>
+                    <div class="app-login-box-container">
+                        <form action="index.html" method="post">
+                            <div class="form-group">
+                                <input type="text" class="form-control" name="login" placeholder="Email Address">
+                            </div>
+                            <div class="form-group">
+                                <input type="password" class="form-control" name="password" placeholder="Password">
+                            </div>
+                            <div class="form-group">
+
+                                <div class="row">
+                                    <div class="col-md-6 col-xs-6">
+                                        <div class="app-checkbox">
+                                            <label><input type="checkbox" name="app-checkbox-1" value="0"> Remember me</label>
+                                        </div>
+                                    </div>
+                                    <div class="col-md-6 col-xs-6">
+                                        <button class="btn btn-success btn-block">Sign In</button>
+                                    </div>
+                                </div>
+                                
+                            </div>
+                        </form>
+                    </div>
+                    <div class="app-login-box-or">
+                        <div class="or">OR</div>
+                    </div>
+                    <div class="app-login-box-container">
+                        <button class="btn btn-facebook btn-block">Connect With Facebook</button>
+                        <button class="btn btn-twitter btn-block">Connect With Twitter</button>
+                    </div>
+                    <div class="app-login-box-footer">
+                        &copy; Boooya 2017. All rights reserved.
+                    </div>
+                </div>
+                                
+            </div>
+            <!-- END APP CONTAINER -->
+           
+        </div>        
+        <!-- END APP WRAPPER -->                
+        
+        <!--
+        <div class="modal fade" id="modal-thanks" tabindex="-1" role="dialog">                        
+            <div class="modal-dialog modal-sm" role="document">                    
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true" class="icon-cross"></span></button>
+                <div class="modal-content">                    
+                    <div class="modal-body">                
+                        <p class="text-center margin-bottom-20">
+                            <img src="assets/images/smile.png" alt="Thank you" style="width: 100px;">
+                        </p>                
+                        <h3 id="modal-thanks-heading" class="text-uppercase text-bold text-lg heading-line-below heading-line-below-short text-center"></h3>
+                        <p class="text-muted text-center margin-bottom-10">Thank you so much for likes</p>
+                        <p class="text-muted text-center">We will do our best to make<br> Boooya template perfect</p>                
+                        <p class="text-center"><button class="btn btn-success btn-clean" data-dismiss="modal">Continue</button></p>
+                    </div>                    
+                </div>
+            </div>            
+        </div>-->
+        
+        <!-- IMPORTANT SCRIPTS -->
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-migrate.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-ui.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/bootstrap/bootstrap.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/moment/moment.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/customscrollbar/jquery.mCustomScrollbar.min.js"></script>
+        <!-- END IMPORTANT SCRIPTS -->
+        <!-- APP SCRIPTS -->
+        <script type="text/javascript" src="../static/js/app.js"></script>
+        <script type="text/javascript" src="../static/js/app_plugins.js"></script>
+        <script type="text/javascript" src="../static/js/app_demo.js"></script>
+        <!-- END APP SCRIPTS -->
+    </body>
+</html>

+ 9 - 0
html/log.html

@@ -0,0 +1,9 @@
+<script type="text/javascript">
+	function httpGet(theUrl)
+	{
+    var xmlHttp = new XMLHttpRequest();
+    xmlHttp.open( "GET", theUrl, false ); // false for synchronous request
+    xmlHttp.send( null );
+    return xmlHttp.responseText;
+	}
+</script>

+ 85 - 0
html/login.html

@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>                        
+        {{ template "head_tmpl" }}
+    </head>
+    <body>        
+        
+        <!-- APP WRAPPER -->
+        <div class="app">
+
+            <!-- START APP CONTAINER -->
+            <div class="app-container">
+                
+                <div class="app-login-box"> <br>                                                           
+                    <div class="app-login-box-title">
+                        <div class="title">Авторизуйтесь</div>               
+                    </div>
+                    <div class="app-login-box-container">
+                        <form action="index.html" method="post">
+                            <div class="form-group">
+                                <input type="text" class="form-control" name="login" placeholder="Логин">
+                            </div>
+                            <div class="form-group">
+                                <input type="password" class="form-control" name="password" placeholder="Пароль">
+                            </div>
+                            <div class="form-group">
+
+                                <div class="row">
+                                    <div class="col-md-6 col-xs-6">
+                                        <div class="app-checkbox">
+                                            <label><input type="checkbox" name="app-checkbox-1" value="0"> Запомнить меня</label>
+                                        </div>
+                                    </div>
+                                    <div class="col-md-6 col-xs-6">
+                                        <button class="btn btn-success btn-block">Войти</button>
+                                    </div>
+                                </div>
+                                
+                            </div>
+                        </form>
+                    </div>
+                    <div class="app-login-box-footer">
+                        &copy; Томский Техникум Информационных Технологий 2020
+                    </div>
+                </div>
+                                
+            </div>
+            <!-- END APP CONTAINER -->
+           
+        </div>        
+        <!-- END APP WRAPPER -->                
+        
+        <!--
+        <div class="modal fade" id="modal-thanks" tabindex="-1" role="dialog">                        
+            <div class="modal-dialog modal-sm" role="document">                    
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true" class="icon-cross"></span></button>
+                <div class="modal-content">                    
+                    <div class="modal-body">                
+                        <p class="text-center margin-bottom-20">
+                            <img src="assets/images/smile.png" alt="Thank you" style="width: 100px;">
+                        </p>                
+                        <h3 id="modal-thanks-heading" class="text-uppercase text-bold text-lg heading-line-below heading-line-below-short text-center"></h3>
+                        <p class="text-muted text-center margin-bottom-10">Thank you so much for likes</p>
+                        <p class="text-muted text-center">We will do our best to make<br> Boooya template perfect</p>                
+                        <p class="text-center"><button class="btn btn-success btn-clean" data-dismiss="modal">Continue</button></p>
+                    </div>                    
+                </div>
+            </div>            
+        </div>-->
+        
+        <!-- IMPORTANT SCRIPTS -->
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-migrate.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-ui.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/bootstrap/bootstrap.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/moment/moment.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/customscrollbar/jquery.mCustomScrollbar.min.js"></script>
+        <!-- END IMPORTANT SCRIPTS -->
+        <!-- APP SCRIPTS -->
+        <script type="text/javascript" src="../static/js/app.js"></script>
+        <script type="text/javascript" src="../static/js/app_plugins.js"></script>
+        <script type="text/javascript" src="../static/js/app_demo.js"></script>
+        <!-- END APP SCRIPTS -->
+    </body>
+</html>

+ 48 - 0
html/nav.html

@@ -0,0 +1,48 @@
+{{ define "navbar" }}
+<div data-type="close-other">
+<nav>
+	<ul>
+		<li class="title">Распределение нагрузки преподавателей</li>
+		<li><a href="/plan/">Учебный план</a></li>
+		<li class="openable" data-type="close-other">
+			<a href="">Нагрузка</a>
+			<ul>
+				<li><a href="/teachercard/">Карточки преподавателей</a></li>
+				<li><a href="/groupcard/">Карточки групп</a></li>
+				<li><a href="/schedule/">Расписание</a></li>
+			</ul>
+		</li>
+		<!-- <li class="openable">
+			<a href=""><span class="nav-icon-hexa">СТ</span>Студенты</a>
+			<ul>
+				
+			</ul>
+		</li> -->
+		<li class="openable">
+			<a href="">Данные</a>
+			<ul>
+				<li><a href="/teacher/">Преподаватели</a></li>
+				<li><a href="/classroom/">Кабинеты</a></li>
+				<li><a href="/group/">Группы</a></li>
+				<li><a href="/subject/">Предметы</a></li>
+				<li><a href="/cycle/">Циклы и модули</a></li>
+				<li><a href="/specialty/">Специальности</a></li>
+			</ul>
+		</li>
+		<li class="openable"><a href=""><span class="nav-icon-hexa">Д</span>Другое</a>
+			<ul>
+				<li><a href="/bellschedule/">Расписание звонков</a></li>
+				<li><a href="/api/">API</a></li>
+			</ul>
+		</li>
+		<li class="openable"><a href=""><span class="nav-icon-hexa">А</span>Архив</a>
+			<ul>
+				<li><a href="/planArchive">Учебные планы</a></li>
+				<li><a href="/teachercardArchive">Карточки преподавателей</a></li>
+				<li><a href="/groupcardArchive">Карточки групп</a></li>
+			</ul>
+		</li>
+</ul>
+</nav>
+</div>
+{{ end }}

+ 199 - 0
html/schedule.html

@@ -0,0 +1,199 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        {{ template "head_tmpl" }}
+    </head>
+    <body>
+
+        <!-- APP WRAPPER -->
+        <div class="app">
+            <!-- START APP CONTAINER -->
+            <div class="app-container" >
+                <!-- START SIDEBAR -->
+                <div class="app-sidebar app-navigation app-navigation-fixed scroll app-navigation-style-default dir-left">
+                {{ template "navbar" }}
+            </div>
+            <!-- END SIDEBAR -->
+
+            <!-- START APP CONTENT -->
+            <div class="app-content" id="app">
+                <!-- START APP HEADER -->
+                <div class="app-header app-header-design-default">
+                    <ul class="app-header-buttons">
+                        <li class="visible-mobile"><a href="#" class="btn btn-link btn-icon" data-sidebar-toggle=".app-sidebar.dir-left"><span class="icon-menu"></span></a></li>
+                        <li class="hidden-mobile"><a href="#" class="btn btn-link btn-icon" data-sidebar-minimize=".app-sidebar.dir-left"><span class="icon-menu"></span></a></li>
+                    </ul>
+                    <!-- END APP HEADER  -->
+
+                    <!-- START PAGE HEADING -->
+                    <div class="app-heading app-heading-bordered app-heading-page">
+                        <div class="title">
+                            <h2>Распределение нагрузки преподавателей</h2>
+                            <p>Здесь можно создать новый учебный план</p>
+                        </div>
+                    </div>
+                    <!-- END PAGE HEADING -->
+
+                    <!-- START PAGE CONTAINER -->
+                    <div class="container">
+                    <div class="block">
+                        <div class="col-md-12">
+                            <div class="app-heading app-heading-small app-heading-condensed padding-left-0">
+                                <div class="title">
+                                    <h2>Расписание занятий</h2>
+                                </div>
+                            </div>
+                            <div class="row">
+                                <div class="col-md-4">
+                                    <!--data-target="#modal-backdrop-disable"-->
+                                    <button class="btn btn-primary" @click="generateSchedule()">Сгенерировать расписание</button>
+                                </div>
+                                <div class="col-md-4">
+                                    
+                                </div>
+                                <div class="col-md-4">
+                                    <div class="btn-group">
+                                        <button class="btn btn-primary btn-icon-fixed dropdown-toggle" data-toggle="dropdown"><span class="fa fa-bars"></span>Экспорт расписания</button>
+                                        <ul class="dropdown-menu dropdown-left">
+                                           
+                                            <li><a href="#" onClick ="$('#sortable-data').tableExport({type:'excel',escape:'false'});"><img src='img/icons/xls.png' width="24"> XLS</a></li>
+                                           
+                                            <li><a href="#" onClick ="$('#sortable-data').tableExport({type:'pdf',escape:'false'});"><img src='img/icons/pdf.png' width="24"> PDF</a></li>
+                                        </ul>
+                                    </div> 
+                                </div>
+                            </div>
+                                <div class="heading-elements">
+                                    
+                                </div>
+                                <br>
+                            <div>
+                                <ul class="nav nav-pills nav-justified">
+                                    <li class="active"><a href="#pills-4" data-toggle="tab" @click="getScheduleForDay(1)">Понедельник</a></li>
+                                    <li><a href="#pills-5" @click="getScheduleForDay(2)">Вторник</a></li>
+                                    <li><a href="#pills-6" @click="getScheduleForDay(3)">Среда</a></li>
+                                    <li><a href="#pills-7" @click="getScheduleForDay(4)">Четверг</a></li>
+                                    <li><a href="#pills-8" @click="getScheduleForDay(5)">Пятница</a></li>
+                                    <li><a href="#pills-9" @click="getScheduleForDay(6)">Суббота</a></li>
+                                </ul>
+                                <div class="tab-content">
+                                    <div class="tab-pane active col-md-3" id="pills-4" v-for='group in scheduleForDay'>
+                                        <table class="table table-bordered table-hover">
+                                            <thead  >
+                                                <tr >
+                                                    <th colspan="4" height="50px" style="font-size: 20pt"><center>${group.Group}</center></th>
+                                                </tr>
+                                            </thead>
+                                            <tbody>
+                                                <tr v-for='tableData in group.Table'>
+                                                    <td>1</td>
+                                                    <td v-for="subj in tableData.Subject.slice(0,1)">${subj}</td>
+                                                    <td  v-for="teacher in tableData.Teacher.slice(0,1)">${teacher}</td>
+                                                    <td v-for="cab in tableData.Cabinet.slice(0,1)">${cab}</td>
+                                                </tr>
+                                            </tbody>
+                                        </table>
+                                    </div>
+                                    <div class="tab-pane" id="pills-5">
+                                        <p>Текст</p>
+                                    </div>
+                                    <div class="tab-pane" id="pills-6">
+                                        <p>Текст</p>
+                                    </div>
+                                    <div class="tab-pane" id="pills-7">
+                                        <p>Текст</p>
+                                    </div>
+                                    <div class="tab-pane" id="pills-8">
+                                        <p>Текст</p>
+                                    </div>
+                                    <div class="tab-pane" id="pills-8">
+                                        <p>Текст</p>
+                                    </div>
+                                    <div class="tab-pane" id="pills-9">
+                                        <p>Текст</p>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    
+                </div>
+                <!-- END APP CONTAINER -->
+                <!-- MODALS -->
+                            <div class="modal fade" id="modal-backdrop-disable" tabindex="-1" role="dialog">
+                                <div class="modal-dialog" role="document">                    
+                                    <div class="modal-content">                    
+                                        <div class="modal-body">
+                                            <div class="form-group">
+                                                <label class="col-md-3 control-label">Начало недели</label>
+                                                <div class="col-md-9">
+                                                    <input type="text" class="mask_date_rev form-control">
+                                                    <span class="help-block">Format: DD-MM-YYYY</span>
+                                                </div>
+                                            </div>  
+                                            <div class="form-group">
+                                                <label class="col-md-3 control-label">Конец недели</label>
+                                                <div class="col-md-9">
+                                                    <input type="text" class="mask_date_rev form-control">
+                                                    <span class="help-block">Format: DD-MM-YYYY</span>
+                                                </div>
+                                            </div>  
+                                            <div class="form-group">
+                                                <label class="col-md-3 control-label">Четная/Нечетная</label>
+                                                <div class="col-md-9">
+                                                    <div class="app-radio inline"> 
+                                                        <label><input type="radio" name="app-radio-2" value="1" checked> Четная</label>
+                                                    </div>
+                                                    <div class="app-radio inline"> 
+                                                        <label><input type="radio" name="app-radio-2" value="0"> Нечетная</label> 
+                                                    </div>
+                                                </div>
+                                            </div>
+                                        </div>
+                                            <div class="modal-footer">
+                                                <button type="button" class="btn btn-link" data-dismiss="modal">Закрыть</button>
+                                                <button type="submit" class="btn btn-default">Сгенерировать</button>
+                                            </div>
+                                        </div>                   
+                                    </div>
+                                </div>            
+                            </div>
+                            </div>
+
+            <script src="https://unpkg.com/vue"></script>
+            <script type="text/javascript" src="../static/js/vendor/maskedinput/jquery.maskedinput.min.js"></script>
+            <!-- THIS PAGE SCRIPTS -->
+            <script type="text/javascript" src="../static/js/vendor/bootstrap-select/bootstrap-select.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/select2/select2.full.min.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/bootstrap-datetimepicker/bootstrap-datetimepicker.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/bootstrap-daterange/daterangepicker.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/multiselect/jquery.multi-select.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/datatables/jquery.dataTables.min.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/datatables/dataTables.bootstrap.min.js"></script>
+            
+            <script type="text/javascript" src="../static/js/vendor/tableexport/tableExport.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/tableexport/jquery.base64.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/tableexport/html2canvas.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/tableexport/jspdf/libs/sprintf.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/tableexport/jspdf/jspdf.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/tableexport/jspdf/libs/base64.js"></script>
+            <!-- END THIS PAGE SCRIPTS -->
+            <!-- IMPORTANT SCRIPTS -->
+            <script type="text/javascript" src="../static/js/vendor/jquery/jquery.min.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/jquery/jquery-migrate.min.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/jquery/jquery-ui.min.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/bootstrap/bootstrap.min.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/moment/moment.min.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/customscrollbar/jquery.mCustomScrollbar.min.js"></script>
+            <!-- END IMPORTANT SCRIPTS -->
+            <script type="text/javascript" src="../static/js/vendor/bootstrap-select/bootstrap-select.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/select2/select2.full.min.js"></script>
+            <!-- APP SCRIPTS -->
+            <script type="text/javascript" src="../static/js/app.js"></script>
+            <script type="text/javascript" src="../static/js/app_plugins.js"></script>
+            <script type="text/javascript" src="../static/js/api/vueSchedule.js"></script>
+
+            <!-- SATISFYING RED BUTTON AT RIGHT CORNER -->
+            <!-- END APP SCRIPTS -->
+        </body>
+    </html>

+ 149 - 0
html/specialty.html

@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<html lang=en>
+    <head>
+        {{ template "head_tmpl" }}
+    </head>
+    <body>
+
+        <div class="app">
+            <!-- START APP CONTAINER -->
+            <div class="app-container" >
+                <!-- START SIDEBAR -->
+                <div class="app-sidebar app-navigation app-navigation-fixed scroll app-navigation-style-default dir-left">
+                {{ template "navbar" }}
+            </div>
+            <!-- END SIDEBAR -->
+
+            <!-- START APP CONTENT -->
+            <div class="app-content">
+                <!-- START APP HEADER -->
+                <div class="app-header app-header-design-default">
+                    <ul class="app-header-buttons">
+                        <li class="visible-mobile"><a href="#" class="btn btn-link btn-icon" data-sidebar-toggle=".app-sidebar.dir-left"><span class="icon-menu"></span></a></li>
+                        <li class="hidden-mobile"><a href="#" class="btn btn-link btn-icon" data-sidebar-minimize=".app-sidebar.dir-left"><span class="icon-menu"></span></a></li>
+                    </ul>
+                    <!-- END APP HEADER  -->
+
+                    <!-- START PAGE HEADING -->
+                    <div class="app-heading app-heading-bordered app-heading-page">
+                        <div class="title">
+                            <h2>Распределение нагрузки преподавателей</h2>
+                            <p>Здесь можно создать новый учебный план</p>
+                        </div>
+                    </div>
+                <div class="container" id="app">
+                    <div class="block">
+                        <div class="col-md-4 col-ms-4 grid-element filter-business">
+                            <div class="tile-basic">
+                                <a href="#" class="preview" data-preview-size="modal-lg">
+                                    <div class="tile-content tile-content-condensed-bottom text-center">
+                                        <button type="button" class="btn btn-success btn-lg">Добавить</button>
+                                    </a>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="col-md-4 col-ms-4 grid-element filter-business">
+                            <div class="tile-basic">
+                                <a href="#" class="preview" data-preview-size="modal-lg">
+                                    <div class="tile-content tile-content-condensed-bottom text-center">
+                                        <button type="button" class="btn btn-warning btn-lg">Редактировать</button>
+                                    </a>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="col-md-4 col-ms-4 grid-element filter-business">
+                            <div class="tile-basic">
+                                <a href="#" class="preview-delete" data-preview-size="modal-lg">
+                                    <div class="tile-content tile-content-condensed-bottom text-center">
+                                        <button type="button" class="btn btn-danger btn-lg">Удалить</button>
+                                    </div>
+                                </a>
+                            </div>
+                        </div>
+                        <!-- модальные окна -->
+                        <div class="modal fade" id="preview-delete" tabindex="1" role="dialog">
+                            <div class="modal-dialog">
+                                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true" class="icon-cross"></span></button>
+                                <div class="modal-content">
+                                    <h1></h1>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="modal fade" id="preview" tabindex="-1" role="dialog">
+                            <div class="modal-dialog">
+                                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true" class="icon-cross"></span></button>
+                                <div class="modal-content">
+                                    <div class="block">
+                                        <h1>Специальности</h1>
+                                        <div class="col-md-12">
+                                            <label>Код специальности</label>
+                                            <div class="input-group">
+                                                <input type="text" class="form-control code" placeholder="09.02.04">
+                                            </div>
+                                        </div>
+                                        <div class="col-md-12">
+                                            <label>Название специальности</label>
+                                            <div class="input-group">
+                                                <input type="text" class="form-control name" placeholder="Программирование в компьютерных системах">
+                                                <div class="app-radio">
+                                                    <label><input type="radio" name="app-radio-1" class="duration-radio" value="1"> 2 года 10 месяцев</label>
+                                                    <label><input type="radio" name="app-radio-1" class="duration-radio" value="2"> 3 года 10 месяцев</label>
+                                                </div>
+                                            </div>
+                                        </div>
+                                        <div class="col-md-12">
+                                            <button type="button" class="btn btn-default" onclick="addSpecialty()">Добавить специальность</button>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <!-- модальные окна -->
+                        <div class="block-content">
+                            <table class="table table-striped table-bordered ">
+                                <h1>Специальности</h1>
+                                <p>Здесь вы можете добавить, удалить или редактировать специальность.</p>
+                                <thead>
+                                    <tr>
+                                        <th>Код специальности</th>
+                                        <th>Название специальности</th>
+                                        <th>Срок обучения</th>
+                                    </tr>
+                                </thead>
+                                <tbody>
+                                    <tr v-for="c in specialties">
+                                        <td>${c.Code}</td>
+                                        <td>${c.Name}</td>
+                                        <td v-if="c.IDDuration === 1">2 года 10 месяцев</td>
+                                        <td v-if="c.IDDuration === 2">3 года 10 месяцев</td>
+                                    </tr>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <!-- END APP CONTAINER -->
+
+        </div>
+        <script src="https://unpkg.com/vue"></script>
+        <script type="text/javascript" src="../static/js/api/vueSpecialty.js"></script>
+        <script type="text/javascript" src="../static/js/api/jsSpecialty.js"></script>
+        <!-- IMPORTANT SCRIPTS -->
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-migrate.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-ui.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/bootstrap/bootstrap.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/moment/moment.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/customscrollbar/jquery.mCustomScrollbar.min.js"></script>
+        <!-- END IMPORTANT SCRIPTS -->
+        <script type="text/javascript" src="../static/js/vendor/bootstrap-select/bootstrap-select.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/select2/select2.full.min.js"></script>
+        <!-- APP SCRIPTS -->
+        <script type="text/javascript" src="../static/js/app.js"></script>
+        <script type="text/javascript" src="../static/js/app_plugins.js"></script>
+        <script type="text/javascript" src="../static/js/app_demo.js"></script>
+        <!-- END APP SCRIPTS -->
+        <script type="text/javascript" src="../static/js/vendor/datatables/jquery.dataTables.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/datatables/dataTables.bootstrap.min.js"></script>
+    </body>

+ 158 - 0
html/subject.html

@@ -0,0 +1,158 @@
+<!DOCTYPE html>
+<html lang=en>
+    <head>
+        <head>
+            {{ template "head_tmpl" }}
+        </head>
+    </head>
+    <body>
+
+        <div class="app">
+            <!-- START APP CONTAINER -->
+            <div class="app-container">
+                <!-- START SIDEBAR -->
+                <div class="app-sidebar app-navigation app-navigation-fixed scroll app-navigation-style-default dir-left">
+                    {{ template "navbar" }}
+                </div>
+                <!-- END SIDEBAR -->
+
+                <!-- START APP CONTENT -->
+                <div class="app-content">
+                    <!-- START APP HEADER -->
+                    <div class="app-header app-header-design-default">
+                        <ul class="app-header-buttons">
+                            <li class="visible-mobile"><a href="#" class="btn btn-link btn-icon" data-sidebar-toggle=".app-sidebar.dir-left"><span class="icon-menu"></span></a></li>
+                            <li class="hidden-mobile"><a href="#" class="btn btn-link btn-icon" data-sidebar-minimize=".app-sidebar.dir-left"><span class="icon-menu"></span></a></li>
+                        </ul>
+                        <!-- END APP HEADER  -->
+
+                        <!-- START PAGE HEADING -->
+                        <div class="app-heading app-heading-bordered app-heading-page">
+                            <div class="title">
+                                <h2>Распределение нагрузки преподавателей</h2>
+                                <p>Здесь можно создать новый учебный план</p>
+                            </div>
+                        </div>
+                <div class="container" id="app">
+                    <div class="block">
+                        <div class="col-md-4 col-ms-4 grid-element filter-business">
+                            <div class="tile-basic">
+                                <a href="#" class="preview" data-preview-size="modal-lg">
+                                    <div class="tile-content tile-content-condensed-bottom text-center">
+                                        <button type="button" class="btn btn-success btn-lg">Добавить</button>
+                                    </a>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="col-md-4 col-ms-4 grid-element filter-business">
+                            <div class="tile-basic">
+                                <a href="#" class="preview" data-preview-size="modal-lg">
+                                    <div class="tile-content tile-content-condensed-bottom text-center">
+                                        <button type="button" class="btn btn-warning btn-lg">Редактировать</button>
+                                    </a>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="col-md-4 col-ms-4 grid-element filter-business">
+                            <div class="tile-basic">
+                                <a href="#" class="preview-delete" data-preview-size="modal-lg">
+                                    <div class="tile-content tile-content-condensed-bottom text-center">
+                                        <button type="button" class="btn btn-danger btn-lg">Удалить</button>
+                                    </div>
+                                </a>
+                            </div>
+                        </div>
+                        
+                        <div class="block-content">
+                            <table class="table table-striped table-bordered">
+                                <h1>Предметы</h1>
+                                <p>Здесь вы можете добавить, удалить или редактировать предметы.</p>
+                                <thead>
+                                    <tr>
+                                        <th>Название предмета</th>
+                                        <th>Сокращенное название</th>
+                                        <th>Профессиональный модуль</th>
+                                    </tr>
+                                </thead>
+                                <tbody>
+                                    <tr v-for="c in subjects">
+                                        <td>${c.Name}</td>
+                                        <td>${c.Shortname}</td>
+                                        <td>${c.ID_professionalmodule}</td>
+                                    </tr>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <!-- END APP CONTAINER -->
+            <!-- модальные окна -->
+                        <div class="modal fade" id="preview" tabindex="-1" role="dialog">
+                            <div class="modal-dialog">
+                                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true" class="icon-cross"></span></button>
+                                <div class="modal-content">
+                                    <div class="block">
+                                        <h1>Предметы</h1>
+                                        <div class="col-md-12">
+                                            <label>Название предмета</label>
+                                            <div class="input-group">
+                                                <input type="text" class="form-control subjectName" placeholder="09.02.04">
+                                            </div>
+                                        </div>
+                                        <div class="col-md-12">
+                                            <label>Сокращенное название</label>
+                                            <div class="input-group">
+                                                <input type="text" class="form-control shortName" placeholder="Программирование в компьютерных системах">
+                                            </div>
+                                        </div>
+
+                                        <div class="col-md-12">
+                                            <label>Профессиональный модуль</label>
+                                            <select class="bs-select " id="selectProfmodule">
+                                                <option>1</option>
+                                                <option>2</option>
+                                                <option>3</option>
+                                                <option>4</option>
+                                            </select>
+                                        </div>
+                                        <div class="form-group">
+                                            <div class="col-md-6">
+                                                <div class="app-checkbox inline">
+                                                    <label><input type="checkbox" class="type" name="app-checkbox-2" value="0" checked="checked"> Лабораторные</label>
+                                                </div>
+                                            </div>
+                                        </div>
+                                            
+                                        <div class="col-md-12">
+                                            <br>
+                                            <button type="button" class="btn btn-default" onclick="addSubject()">Добавить предмет</button>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <!-- модальные окна -->
+
+        </div>
+        <script src="https://unpkg.com/vue"></script>
+        <script type="text/javascript" src="../static/js/api/vueSubject.js"></script>
+        <!-- IMPORTANT SCRIPTS -->
+        <!--<script type="text/javascript" src="../static/js/api/jsSubject.js"></script> -->
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-migrate.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/jquery/jquery-ui.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/bootstrap/bootstrap.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/moment/moment.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/customscrollbar/jquery.mCustomScrollbar.min.js"></script>
+        <!-- END IMPORTANT SCRIPTS -->
+        <script type="text/javascript" src="../static/js/vendor/bootstrap-select/bootstrap-select.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/select2/select2.full.min.js"></script>
+        <!-- APP SCRIPTS -->
+        <script type="text/javascript" src="../static/js/app.js"></script>
+        <script type="text/javascript" src="../static/js/app_plugins.js"></script>
+        <script type="text/javascript" src="../static/js/app_demo.js"></script>
+        <!-- END APP SCRIPTS -->
+        <script type="text/javascript" src="../static/js/vendor/datatables/jquery.dataTables.min.js"></script>
+        <script type="text/javascript" src="../static/js/vendor/datatables/dataTables.bootstrap.min.js"></script>
+    </body>

+ 148 - 0
html/teacher.html

@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        {{ template "head_tmpl" }}
+    </head>
+    <body>
+        <!-- APP WRAPPER -->
+        <div class="app" id="app">
+            <!-- START APP CONTAINER -->
+            <div class="app-container">
+                <!-- START SIDEBAR -->
+                <div class="app-sidebar app-navigation app-navigation-fixed scroll app-navigation-style-default dir-left">
+                {{ template "navbar" }}
+            </div>
+            <!-- END SIDEBAR -->
+            <!-- START APP CONTENT -->
+            <div class="app-content">
+
+                <!-- START APP HEADER -->
+                <div class="app-header app-header-design-default">
+                    <ul class="app-header-buttons">
+                        <li class="visible-mobile"><a href="#" class="btn btn-link btn-icon"
+                            data-sidebar-toggle=".app-sidebar.dir-left"><span
+                            class="icon-menu"></span></a></li>
+                            <li class="hidden-mobile"><a href="#" class="btn btn-link btn-icon"
+                                data-sidebar-minimize=".app-sidebar.dir-left"><span
+                                class="icon-menu"></span></a></li>
+                            </ul>
+                            <!-- END APP HEADER  -->
+                            <!-- START PAGE HEADING -->
+                            <div class="app-heading app-heading-bordered app-heading-page">
+                                <div class="title">
+                                    <h2>Информация по преподавателям</h2>
+                                    <p>Здесь можно редактировать информацию о преподавателях</p>
+                                </div>
+                            </div>
+                            <!-- END PAGE HEADING -->
+                            <!-- START PAGE CONTAINER -->
+                            <div class="container" >
+                                <!-- START BLOCk -->
+                                <div class="block">
+                                    <div class="row" >
+                                        <div class="col-md-4">
+                                            <button type="button" class="btn btn-success btn-lg" data-toggle="modal" data-target="#modal-default">Добавить</button>
+                                        </div>
+                                        <div class="col-md-4" >
+                                            <button type="button" class="btn btn-danger btn-lg">Удалить</button>
+                                        </div>
+                                        <div class="col-md-4">
+                                            <button type="button" class="btn btn-warning btn-lg">Редактировать</button>
+                                        </div>
+                                    </div>
+                                    <br>
+                                    <table class="table table-striped table-bordered ">
+                                        <thead>
+                                            <tr>
+                                                <th>Фамилия</th>
+                                                <th>Имя</th>
+                                                <th>Отчество</th>
+                                                <th>Закреплённый кабинет</th>
+                                            </tr>
+                                        </thead>
+                                        <tbody>
+                                            <tr v-for="c in teachers">
+                                                <td>${c.Name}</td>
+                                                <td>${c.Surname}</td>
+                                                <td>${c.Patronymic}</td>
+                                                <td>${c.IDClassroom}</td>
+                                            </tr>
+                                        </tbody>
+                                    </table>
+                                </div>
+                            </div>
+                            <!-- END BLOCk -->
+                        </div>
+                        <!-- END PAGE CONTAINER -->
+                    </div>
+                    <!-- END APP CONTENT -->
+                </div>
+                <!-- END APP CONTAINER -->
+                <div class="modal fade" id="modal-default" tabindex="-1" role="dialog" aria-labelledby="modal-default-header">
+                            <div class="modal-dialog modal-lg" role="document">
+                                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true" class="icon-cross"></span></button>
+                                <div class="modal-content">
+                                    <div class="block">
+                                        <div class="modal-header">
+                                            <h4 class="modal-title" id="modal-default-header">Добавление кабинета</h4>    
+                                        </div>
+                                        <div class="form-group">
+                                            <div class="col-md-3">
+                                                <label>Фамилия</label>
+                                            </div>
+                                            <div class="col-md-9">
+                                                <input type="text" class="form-control surname">
+                                            </div>
+                                        </div>
+                                        <div class="form-group">
+                                            <label class="control-label col-md-3">Имя</label>
+                                            <div class="col-md-9">
+                                                <input type="text" class="form-control name">
+                                            </div>
+                                        </div>
+                                        <div class="form-group">
+                                            <label class="control-label col-md-3">Отчество</label>
+                                            <div class="col-md-9">
+                                                <input type="text" class="form-control patronymic">
+                                            </div>
+                                        </div>
+                                        
+                                        <div class="form-group">
+                                            <div class="col-md-3">
+                                                <label>Закрепленный кабинет</label>
+                                            </div>
+                                            <div class="col-md-9">
+                                                <select id="selectClassroom">
+                                                    <option v-for="cr in classrooms" v-bind:value="cr.Name">${cr.Name}</option>
+                                                </select>
+
+                                            </div>
+                                        </div>
+                                        <div class="modal-footer">
+                                            <button type="button" class="btn btn-link" data-dismiss="modal">Закрыть</button>
+                                            <button type="button" class="btn btn-default" onclick="addTeacher()">Добавить</button>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+            <script src="https://unpkg.com/vue"></script>
+            <script type="text/javascript" src="../static/js/api/vueTeacher.js"></script>
+            <script type="text/javascript" src="../static/js/api/apiTeacher.js"></script>
+            <!-- IMPORTANT SCRIPTS -->
+            <script type="text/javascript" src="../static/js/vendor/jquery/jquery.min.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/jquery/jquery-migrate.min.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/jquery/jquery-ui.min.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/bootstrap/bootstrap.min.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/moment/moment.min.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/customscrollbar/jquery.mCustomScrollbar.min.js"></script>
+            <!-- END IMPORTANT SCRIPTS -->
+            <script type="text/javascript" src="../static/js/vendor/bootstrap-select/bootstrap-select.js"></script>
+            <script type="text/javascript" src="../static/js/vendor/select2/select2.full.min.js"></script>
+            <!-- APP SCRIPTS -->
+            <script type="text/javascript" src="../static/js/app.js"></script>
+            <script type="text/javascript" src="../static/js/app_plugins.js"></script>
+            <!-- END APP SCRIPTS -->
+        </body>
+    </html>

文件差異過大導致無法顯示
+ 377 - 0
html/teacherscard.html


+ 110 - 0
input/groups.json

@@ -0,0 +1,110 @@
+[
+	{
+		"name": "101",
+		"quantity": 20,
+		"subjects": [
+			{
+				"name": "subject_one",
+				"teacher": "teacher_one",
+				"is_computer": true,
+				"lessons": {
+					"theory": 2,
+					"practice": 2,
+					"week": 6
+				}
+			},
+			{
+				"name": "subject_two",
+				"teacher": "teacher_two",
+				"is_computer": true,
+				"lessons": {
+					"theory": 2,
+					"practice": 2,
+					"week": 6
+				}
+			},
+			{
+				"name": "subject_three",
+				"teacher": "teacher_three",
+				"is_computer": false,
+				"lessons": {
+					"theory": 2,
+					"practice": 2,
+					"week": 6
+				}
+			}
+		]
+	},
+	{
+		"name": "102",
+		"quantity": 20,
+		"subjects": [
+			{
+				"name": "subject_one",
+				"teacher": "teacher_one",
+				"is_computer": true,
+				"lessons": {
+					"theory": 2,
+					"practice": 2,
+					"week": 6
+				}
+			},
+			{
+				"name": "subject_two",
+				"teacher": "teacher_two",
+				"is_computer": true,
+				"lessons": {
+					"theory": 2,
+					"practice": 2,
+					"week": 6
+				}
+			},
+			{
+				"name": "subject_three",
+				"teacher": "teacher_three",
+				"is_computer": false,
+				"lessons": {
+					"theory": 2,
+					"practice": 2,
+					"week": 6
+				}
+			}
+		]
+	},
+	{
+		"name": "103",
+		"quantity": 20,
+		"subjects": [
+			{
+				"name": "subject_one",
+				"teacher": "teacher_one",
+				"is_computer": true,
+				"lessons": {
+					"theory": 2,
+					"practice": 2,
+					"week": 6
+				}
+			},
+			{
+				"name": "subject_two",
+				"teacher": "teacher_two",
+				"is_computer": true,
+				"lessons": {
+					"theory": 2,
+					"practice": 2,
+					"week": 6
+				}
+			},
+			{
+				"name": "subject_three",
+				"teacher": "teacher_three",
+				"is_computer": false,
+				"lessons": {
+					"theory": 2,
+					"practice": 2,
+					"week": 6
+				}
+			}
+		]
+	}
+]

+ 41 - 0
input/teachers.json

@@ -0,0 +1,41 @@
+[
+	{
+		"name": "teacher_one",
+		"cabinets": [
+			{
+				"name": "201",
+				"is_computer": false
+			},
+			{
+				"name": "202",
+				"is_computer": true
+			}
+		]
+	},
+	{
+		"name": "teacher_two",
+		"cabinets": [
+			{
+				"name": "301",
+				"is_computer": false
+			},
+			{
+				"name": "302",
+				"is_computer": true
+			}
+		]
+	},
+	{
+		"name": "teacher_three",
+		"cabinets": [
+			{
+				"name": "401",
+				"is_computer": false
+			},
+			{
+				"name": "402",
+				"is_computer": true
+			}
+		]
+	}
+]

+ 0 - 0
log/R0R2CL~J.LOG


+ 0 - 0
log/RBFZWE~V.LOG


+ 0 - 0
log/RS83M3~S.LOG


+ 0 - 0
log/RXYWKY~C.LOG


+ 3 - 0
log/Requests_API.log

@@ -0,0 +1,3 @@
+[11:22AM] GET request from 192.168.13.35:49050 to /api/teacher/
+[11:22AM] GET request from 192.168.13.35:49050 to /api/teacher/
+[11:22AM] GET request from 192.168.13.35:49050 to /api/group/

+ 3 - 0
log/Requests_URL.log

@@ -0,0 +1,3 @@
+[11:22] Request from 192.168.13.35:49048 to /groupcard/
+[11:22] Request from 192.168.13.35:49048 to /groupcard/
+[11:22] Request from 192.168.13.35:49048 to /group/

+ 0 - 0
log/error.log


二進制
main


+ 179 - 0
main.go

@@ -0,0 +1,179 @@
+package main
+
+import (
+	"./api"
+	"./settings"
+	"fmt"
+	"net/http"
+	"os"
+	"time"
+	// "./schedule"
+	"github.com/jinzhu/gorm"
+	_ "github.com/jinzhu/gorm/dialects/mysql"
+)
+
+const (
+	HTMLPATH    = "html/"
+	PATH_STATIC = "static/"
+	NAVPATH     = "html/nav.html"
+	HEADPATH    = "html/head.html"
+)
+
+func init() {
+	var err error
+	settings.DB, err = gorm.Open("mysql", settings.CONSTR)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	settings.DB.SingularTable(true)
+}
+
+func main() {
+	http.Handle("/static/", http.StripPrefix(
+		"/static/",
+		handleFileServer(http.Dir(PATH_STATIC))),
+	)
+	_, err := os.Create("log/Requests_API.log")
+	if err != nil {
+		fmt.Println("api log file not created")
+		return
+	}
+	t := time.Now()
+	fmt.Println("[", t.Format(settings.TimeLayout), "]", "API log file can be found at log/Requests_API.log")
+
+	_, err = os.Create("log/Requests_URL.log")
+	if err != nil {
+		fmt.Println("url log file not created")
+		return
+	}
+	fmt.Println("[", t.Format(settings.TimeLayout), "]", "URL log file can be found at log/Requests_URL.log")
+
+	_, err = os.Create("log/error.log")
+	if err != nil {
+		fmt.Println("Error log file not created")
+		return
+	}
+	fmt.Println("[", t.Format(settings.TimeLayout), "]", "Error log file can be found at log/error.log")
+
+	// API functions handling start
+	http.HandleFunc("/api/teacher/", api.TeacherRoute)
+	http.HandleFunc("/api/classroom/", api.ClassroomRoute)
+	http.HandleFunc("/api/classroom/computer", api.GetClassroomByComputer)
+	http.HandleFunc("/api/classroom/lecture", api.GetClassroomByComputer)
+	http.HandleFunc("/api/classroom/name/", api.ClassroomByNumber)
+	http.HandleFunc("/api/group/", api.GroupRoute)
+	http.HandleFunc("/api/group/specialty/", api.GetGroupBySpecialty)
+	http.HandleFunc("/api/schedule/generate", api.Generate)
+	http.HandleFunc("/api/subject/module/", api.GetSubjectByModule)
+	http.HandleFunc("/api/subject/", api.SubjectRoute)
+	http.HandleFunc("/api/module/", api.ModuleApi)
+	http.HandleFunc("/api/cycle/", api.CycleApi)
+	http.HandleFunc("/api/specialty/", api.SpecialtyRoute)
+	http.HandleFunc("/api/building/", api.GetBuilding)
+	http.HandleFunc("/api/groupschedule/", api.ScheduleOfGroupRoute)
+	http.HandleFunc("/api/bellschedule/", api.BellScheduleRoute)
+	http.HandleFunc("/api/attestation/", api.AttestationRoute)
+	http.HandleFunc("/api/semester/", api.SemesterRoute)
+	http.HandleFunc("/api/studyplan/", api.StudyplanRoute)
+	http.HandleFunc("/api/subjectofplan/", api.SubjectofplanRoute)
+	http.HandleFunc("/api/subjecttype/", api.SubjecttypeRoute)
+	http.HandleFunc("/api/logs", testPage)
+	http.HandleFunc("/api/getteachers", api.GetDataTeachers)
+	http.HandleFunc("/api/getgroups/", api.GetDataGroups)
+	// API functions handling end
+
+	// HTTP pages handling start
+	http.HandleFunc("/", indexPage)
+	http.HandleFunc("/plan/", planPage)
+	http.HandleFunc("/teacher/", teacherPage)
+	http.HandleFunc("/classroom/", classroomPage)
+	http.HandleFunc("/groupcard/", groupCardPage)
+	http.HandleFunc("/schedule/", schedulePage)
+	http.HandleFunc("/teachercard/", teacherCardPage)
+	http.HandleFunc("/group/", groupPage)
+	http.HandleFunc("/cycle/", cyclePage)
+	http.HandleFunc("/subject/", subjectPage)
+	http.HandleFunc("/specialty/", specialtyPage)
+	http.HandleFunc("/bellschedule/", bellPage)
+	http.HandleFunc("/api/", apiPage)
+	http.HandleFunc("/auth/", loginPage)
+	http.HandleFunc("/api/modelsDownload", downloadModels)
+	http.HandleFunc("/wekan", wekanRedirect)
+	http.HandleFunc("/test/", testPage) // testing token
+	// HTTP pages handling end
+
+	api.PrintConsole("Server is listening")
+
+	http.ListenAndServe(":80", nil)
+}
+
+func wekanRedirect(w http.ResponseWriter, r *http.Request){
+	if r.URL.Path == "/wekan" || r.URL.Path == "/wekan/"{
+		http.Redirect(w, r, "http://192.168.14.173:8000", 301)
+		return
+	}
+}
+
+func testPage(w http.ResponseWriter, r *http.Request) {
+	if api.CheckToken(r) {
+		fmt.Println("Access granted")
+	}
+	fmt.Println("Access denied")
+}
+
+func downloadModels(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", "models.txt"))
+	http.ServeFile(w, r, "models.txt")
+}
+
+func RenameLogFiles() {
+	now := time.Now()
+	t := now.Format("2 Jan 2006 15:04:05")
+
+	newpath := "log/Requests_API " + t + ".log"
+	err := os.Rename("log/Requests_API.log", newpath)
+
+	if err != nil {
+		fmt.Println("Error during saving API log file")
+	}
+
+	newpath = "log/Requests_URL " + t + ".log"
+	err = os.Rename("log/Requests_URL.log", newpath)
+
+	if err != nil {
+		fmt.Println("Error during saving URL log file")
+	}
+}
+
+func shutdown(w http.ResponseWriter, r *http.Request) {
+	showRequest(r)
+	now := time.Now()
+	t := now.Format(time.Stamp)
+	fmt.Println("Shutting down...")
+	newpath := "log/Requests_API " + t + ".log"
+	err := os.Rename("log/Requests_API.log", newpath)
+
+	if err != nil {
+		fmt.Println("Error during saving API log file")
+	}
+
+	newpath = "log/Requests_URL " + t + ".log"
+	err = os.Rename("log/Requests_URL.log", newpath)
+
+	if err != nil {
+		fmt.Println("Error during saving URL log file")
+	}
+
+	os.Exit(0)
+}
+
+func handleFileServer(fs http.FileSystem) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if _, err := fs.Open(r.URL.Path); os.IsNotExist(err) {
+			http.Redirect(w, r, "/404Err", 404)
+			return
+		}
+		http.FileServer(fs).ServeHTTP(w, r)
+	})
+}

+ 109 - 0
models.txt

@@ -0,0 +1,109 @@
+package api
+
+import "time"
+
+type Subject struct {
+	ID                    uint
+	Name                  string
+	Shortname             string
+	ID_professionalmodule uint
+}
+
+type Professionalmodule struct {
+	ID        uint
+	Name      string
+	Shortname string
+	IDCycle   uint
+}
+
+type Cycle struct {
+	ID        uint
+	Name      string
+	Shortname string
+}
+
+type Lesson struct {
+	ID        uint
+	Timestart time.Time
+	Timeend   time.Time
+}
+
+type Attestation struct {
+	ID        uint
+	Name      string
+	Shortname string
+}
+
+type SubjectOfGroup struct {
+	ID            uint
+	IDSubject     uint
+	IDGroup       uint
+	IDTeacher     uint
+	IDSemester    uint
+	IDAttestation uint
+	Hoursquantity uint
+}
+
+type Semester struct {
+	ID            uint
+	WeeksQuantity uint
+}
+
+type Teacher struct {
+	ID          uint
+	Name        string
+	IDClassroom uint
+	Surname     string
+	Patronymic  string
+}
+
+type ScheduleOfGroup struct {
+	ID             uint
+	IDSubject      uint
+	IDGroup        uint
+	IDSchedule     uint
+	IDLessonNumber uint
+	IDClassroom    uint
+}
+
+type Schedule struct {
+	ID         uint
+	IsShort    bool
+	IDGroup    uint
+	IsEvenWeek bool
+	Weekday    string
+}
+
+type Classroom struct {
+	ID            uint
+	Placequantity uint
+	Iscomputer    bool
+	IDBuilding    uint
+	Name          string
+}
+
+type Building struct {
+	ID      uint
+	Address string
+}
+
+type Group struct {
+	ID          uint
+	IDSpecialty uint
+	Year        uint
+	IDTeacher   uint
+	Groupnumber string
+}
+
+type Specialty struct {
+	ID         uint
+	Code       string
+	Name       string
+	IDDuration uint
+}
+
+type DurationOfStudy struct {
+	ID            uint
+	Yearsquantity uint
+}
+

+ 353 - 0
schedule/generator.go

@@ -0,0 +1,353 @@
+package schedule
+
+import (
+    "fmt"
+    "strconv"
+    "encoding/json"
+    "github.com/tealeg/xlsx"
+)
+
+func NewGenerator(data *Generator) *Generator {
+    return &Generator{
+        Day: data.Day,
+        Debug: data.Debug,
+        Groups: data.Groups,
+        Teachers: data.Teachers,
+        Blocked: make(map[string]bool),
+        Reserved: Reserved{
+            Teachers: make(map[string][]bool),
+            Cabinets: make(map[string][]bool),
+        },
+    }
+}
+
+func (gen *Generator) NewSchedule(group string) *Schedule {
+    return &Schedule{
+        Day: gen.Day,
+        Group: group,
+        Table: make([]Row, NUM_TABLES),
+    }
+}
+
+func ReadGroups(filename string) map[string]*Group {
+    var (
+        groups = make(map[string]*Group)
+        groupsList []GroupJSON
+    )
+    data := readFile(filename)
+    err := json.Unmarshal([]byte(data), &groupsList)
+    if err != nil {
+        return nil
+    }
+    for _, gr := range groupsList {
+        groups[gr.Name] = &Group{
+            Name: gr.Name,
+            Quantity: gr.Quantity,
+        }
+        groups[gr.Name].Subjects = make(map[string]*Subject)
+        for _, sb := range gr.Subjects {
+            if _, ok := groups[gr.Name].Subjects[sb.Name]; ok {
+                groups[gr.Name].Subjects[sb.Name].Teacher2 = sb.Teacher
+                continue
+            }
+            groups[gr.Name].Subjects[sb.Name] = &Subject{
+                Name: sb.Name,
+                Teacher: sb.Teacher,
+                IsComputer: sb.IsComputer,
+                SaveWeek: sb.Lessons.Week,
+                Theory: sb.Lessons.Theory,
+                Practice: Subgroup{
+                    A: sb.Lessons.Practice,
+                    B: sb.Lessons.Practice,
+                },
+                WeekLessons: Subgroup{
+                    A: sb.Lessons.Week,
+                    B: sb.Lessons.Week,
+                },
+            }
+        }
+    }
+    return groups
+}
+
+func ReadTeachers(filename string) map[string]*Teacher {
+    var (
+        teachers = make(map[string]*Teacher)
+        teachersList []Teacher
+    )
+    data := readFile(filename)
+    err := json.Unmarshal([]byte(data), &teachersList)
+    if err != nil {
+        return nil
+    }
+    for _, tc := range teachersList {
+        teachers[tc.Name] = &Teacher{
+            Name: tc.Name,
+            Cabinets: tc.Cabinets,
+        }
+    }
+    return teachers
+}
+
+const (
+    OUTDATA = "output/"
+)
+func (gen *Generator) Template() [][]*Schedule {
+    var (
+        weekLessons = make([][]*Schedule, 7)
+        generator = new(Generator)
+        file *xlsx.File
+        name string
+    )
+    unpackJSON(packJSON(gen), generator)
+    if gen.Debug {
+        file, name = CreateXLSX(OUTDATA + "template.xlsx")
+    }
+    for i := generator.Day; i < generator.Day+7; i++ {
+        weekLessons[i % 7] = generator.Generate(nil)
+        if gen.Debug {
+            generator.WriteXLSX(
+                file,
+                name,
+                weekLessons[i],
+                int(i),
+            )
+        }
+    }
+    return weekLessons
+}
+
+func (gen *Generator) Generate(template [][]*Schedule) []*Schedule {
+    var (
+        list   []*Schedule
+        templt []*Schedule
+        groups = getGroups(gen.Groups)
+    )
+    if template == nil {
+        templt = nil
+    } else {
+        templt = template[gen.Day]
+    }
+    for _, group := range groups {
+        var (
+            schedule = gen.NewSchedule(group.Name)
+            subjects = getSubjects(group.Subjects)
+            countLessons = new(Subgroup)
+        )
+        if gen.Day == SUNDAY {
+            list = append(list, schedule)
+            for _, subject := range subjects {
+                saved := gen.Groups[group.Name].Subjects[subject.Name].SaveWeek
+                gen.Groups[group.Name].Subjects[subject.Name].WeekLessons.A = saved
+                gen.Groups[group.Name].Subjects[subject.Name].WeekLessons.B = saved
+            }
+            continue
+        }
+        for _, subject := range subjects {
+            switch {
+            case gen.haveTheoreticalLessons(subject):
+                if gen.Debug {
+                    fmt.Println(group.Name, subject.Name, ": not splited THEORETICAL;")
+                }
+                gen.tryGenerate(ALL, THEORETICAL, group, subject, schedule, countLessons, templt)
+            // Практические пары начинаются только после завершения всех теоретических.
+            default:
+                // Если подгруппа неделимая, тогда провести практику в виде полной пары.
+                // Иначе разделить практику на две подгруппы.
+                if !gen.withSubgroups(group.Name) {
+                    if gen.Debug {
+                        fmt.Println(group.Name, subject.Name, ": not splited PRACTICAL;")
+                    }
+                    gen.tryGenerate(ALL, PRACTICAL, group, subject, schedule, countLessons, templt)
+                } else {
+                    switch RandSubgroup() {
+                    case A:
+                        if gen.Debug {
+                            fmt.Println(group.Name, subject.Name, ": splited (A -> B);")
+                        }
+                        gen.tryGenerate(A, PRACTICAL, group, subject, schedule, countLessons, templt)
+                        gen.tryGenerate(B, PRACTICAL, group, subject, schedule, countLessons, templt)
+                    case B:
+                        if gen.Debug {
+                            fmt.Println(group.Name, subject.Name, ": splited (B -> A);")
+                        }
+                        gen.tryGenerate(B, PRACTICAL, group, subject, schedule, countLessons, templt)
+                        gen.tryGenerate(A, PRACTICAL, group, subject, schedule, countLessons, templt)
+                    }
+                }
+            }
+        }
+        list = append(list, schedule)
+    }
+    gen.Reserved.Teachers = make(map[string][]bool)
+    gen.Reserved.Cabinets = make(map[string][]bool)
+    gen.Day = (gen.Day + 1) % 7
+    return sortSchedule(list)
+}
+
+func CreateXLSX(filename string) (*xlsx.File, string) {
+    file := xlsx.NewFile()
+    _, err := file.AddSheet("Init")
+    if err != nil {
+        return nil, ""
+    }
+    err = file.Save(filename)
+    if err != nil {
+        return nil, ""
+    }
+    return file, filename
+}
+
+func (gen *Generator) WriteXLSX(file *xlsx.File, filename string, schedule []*Schedule, iter int) error {
+    const (
+        colWidth = 30
+        rowHeight = 30
+    )
+
+    var (
+        MAXCOL = uint(3)
+    )
+
+    rowsNext := uint(len(schedule)) / MAXCOL
+    if rowsNext == 0 || uint(len(schedule)) % MAXCOL != 0 {
+        rowsNext += 1
+    }
+
+    var (
+        
+        colNum = uint(NUM_TABLES + 2)
+        
+        row = make([]*xlsx.Row, colNum * rowsNext) //  * (rowsNext + 1)
+        cell *xlsx.Cell
+        dayN = gen.Day
+        day = ""
+    )
+
+    if dayN == SUNDAY {
+        dayN = SATURDAY
+    } else {
+        dayN -= 1
+    }
+
+    switch dayN {
+    case SUNDAY: day = "Sunday"
+    case MONDAY: day = "Monday"
+    case TUESDAY: day = "Tuesday"
+    case WEDNESDAY: day = "Wednesday"
+    case THURSDAY: day = "Thursday"
+    case FRIDAY: day = "Friday"
+    case SATURDAY: day = "Saturday"
+    }
+
+    sheet, err := file.AddSheet(day + "-" + strconv.Itoa(iter))
+    if err != nil {
+        return err
+    }
+
+    sheet.SetColWidth(2, int(MAXCOL)*3+1, COL_W)
+
+    for r := uint(0); r < rowsNext; r++ {
+        for i := uint(0); i < colNum; i++ {
+            row[(r*colNum)+i] = sheet.AddRow() // (r*rowsNext)+
+            row[(r*colNum)+i].SetHeight(ROW_H)
+            cell = row[(r*colNum)+i].AddCell()
+            if i == 0 {
+                cell.Value = "Пара"
+                continue
+            }
+            cell.Value = strconv.Itoa(int(i-1))
+        }
+    }
+
+    index := uint(0)
+    exit: for r := uint(0); r < rowsNext; r++ {
+        for i := uint(0); i < MAXCOL; i++ {
+            if uint(len(schedule)) <= index {
+                break exit
+            }
+
+            savedCell := row[(r*colNum)+0].AddCell()
+            savedCell.Value = "Группа " + schedule[index].Group
+
+            cell = row[(r*colNum)+0].AddCell()
+            cell = row[(r*colNum)+0].AddCell()
+
+            savedCell.Merge(2, 0)
+
+            cell = row[(r*colNum)+1].AddCell()
+            cell.Value = "Предмет"
+
+            cell = row[(r*colNum)+1].AddCell()
+            cell.Value = "Преподаватель"
+
+            cell = row[(r*colNum)+1].AddCell()
+            cell.Value = "Кабинет"
+
+            for j, trow := range schedule[index].Table {
+                cell = row[(r*colNum)+uint(j)+2].AddCell()
+                if trow.Subject[A] == trow.Subject[B] {
+                    cell.Value = trow.Subject[A]
+                } else {
+                    if trow.Subject[A] != "" {
+                        cell.Value = trow.Subject[A] + " (A)"
+                    }
+                    if trow.Subject[B] != "" {
+                        cell.Value += "\n" + trow.Subject[B] + " (B)"
+                    }
+                }
+
+                cell = row[(r*colNum)+uint(j)+2].AddCell()
+                if trow.Teacher[A] == trow.Teacher[B] {
+                    cell.Value = trow.Teacher[A]
+                } else {
+                    if trow.Teacher[A] != "" {
+                        cell.Value = trow.Teacher[A]
+                    }
+                    if trow.Teacher[B] != "" {
+                        cell.Value += "\n" + trow.Teacher[B]
+                    }
+                }
+
+                sheet.SetColWidth(colWidthForCabinets(int(j)))
+                cell = row[(r*colNum)+uint(j)+2].AddCell()
+                if trow.Cabinet[A] == trow.Cabinet[B] {
+                    cell.Value = trow.Cabinet[A]
+                } else {
+                    if trow.Cabinet[A] != "" {
+                        cell.Value = trow.Cabinet[A]
+                    }
+                    if trow.Cabinet[B] != "" {
+                        cell.Value += "\n" + trow.Cabinet[B]
+                    }
+                }
+            }
+
+            index++
+        }
+    }
+
+    err = file.Save(filename)
+    if err != nil {
+        return err
+    }
+
+    return nil
+}
+
+func RandSubgroup() SubgroupType {
+    return SubgroupType(random(0, 1))
+}
+
+func Load(filename string) *Generator {
+    var generator = new(Generator)
+    jsonData := readFile(filename)
+    err := json.Unmarshal([]byte(jsonData), generator)
+    if err != nil {
+        return nil
+    }
+    return generator
+}
+
+func (gen *Generator) Dump(filename string) error {
+    return writeJSON(filename, gen)
+}

+ 609 - 0
schedule/localdata.go

@@ -0,0 +1,609 @@
+package schedule
+
+import (
+    "os"
+    "sort"
+    "time"
+    "errors"
+    "math/rand"
+    "encoding/json"
+)
+
+func init() {
+    rand.Seed(time.Now().UnixNano())
+}
+
+func (gen *Generator) tryGenerate(
+    subgroup SubgroupType, 
+    subjtype SubjectType, 
+    group *Group, 
+    subject *Subject, 
+    schedule *Schedule, 
+    countl *Subgroup, 
+    template []*Schedule,
+) {
+    flag := false
+startAgain:
+    nextLesson: for lesson := uint(0); lesson < NUM_TABLES; lesson++ {
+        // Если лимит пар на день окончен, тогда прекратить ставить пары группе.
+        if gen.isLimitLessons(subgroup, countl) {
+            break nextLesson
+        }
+
+        // Если это полная группа и у неё не осталось теоретических занятий, тогда пропустить этот предмет. 
+        if subjtype == THEORETICAL && !gen.haveTheoreticalLessons(subject) {
+            break nextLesson
+        }
+
+        // Если это подгруппа и у неё не осталось практических занятий, тогда пропустить этот предмет.
+        if subjtype == PRACTICAL && !gen.havePracticalLessons(subgroup, subject) {
+            break nextLesson
+        }
+
+        // Если учитель заблокирован (не может присутствовать на занятиях) или
+        // лимит пар на текущую неделю для предмета завершён, тогда пропустить этот предмет.
+        if gen.inBlocked(subject.Teacher) || gen.notHaveWeekLessons(subgroup, subject) {
+            break nextLesson
+        }
+
+        isAfter := false
+        savedLesson := lesson
+
+        // [ I ] Первая проверка.
+        switch subgroup {
+        case ALL:
+            // Если две подгруппы стоят друг за другом, тогда исключить возможность добавления полной пары.
+            for i := uint(0); i < NUM_TABLES-1; i++ {
+                if  gen.cellIsReserved(A, schedule, i) && !gen.cellIsReserved(B, schedule, i) && 
+                    gen.cellIsReserved(B, schedule, i+1) && !gen.cellIsReserved(A, schedule, i+1) ||
+                    gen.cellIsReserved(B, schedule, i) && !gen.cellIsReserved(A, schedule, i) && 
+                    gen.cellIsReserved(A, schedule, i+1) && !gen.cellIsReserved(B, schedule, i+1) {
+                        break nextLesson
+                    }
+            }
+
+            // Если между двумя разными подгруппами находятся окна, тогда посчитать сколько пустых окон.
+            // Если их количество = 1, тогда попытаться подставить полную пару под это окно. 
+            // Если не получается, тогда не ставить полную пару.
+            cellSubgroupReserved := false
+            indexNotReserved := uint(0)
+            cellIsNotReserved := 0
+            for i := uint(0); i < NUM_TABLES; i++ {
+                if  gen.cellIsReserved(A, schedule, i) && !gen.cellIsReserved(B, schedule, i) ||
+                    gen.cellIsReserved(B, schedule, i) && !gen.cellIsReserved(A, schedule, i) {
+                        if cellIsNotReserved != 0 {
+                            if cellIsNotReserved == 1 {
+                                lesson = indexNotReserved
+                                goto tryAfter
+                            }
+                            break nextLesson
+                        }
+                        cellSubgroupReserved = true
+                    }
+                if !gen.cellIsReserved(A, schedule, i) && !gen.cellIsReserved(B, schedule, i) && cellSubgroupReserved {
+                    if cellIsNotReserved == 0 {
+                        indexNotReserved = i
+                    }
+                    cellIsNotReserved += 1
+                }
+            }
+
+            switch {
+            case    lesson > 1 && (gen.cellIsReserved(A, schedule, lesson-1) || gen.cellIsReserved(B, schedule, lesson-1)) &&
+                    !(gen.cellIsReserved(A, schedule, lesson+1) || gen.cellIsReserved(B, schedule, lesson+1)): // pass
+            default: 
+                // "Подтягивать" полные пары к уже существующим [перед].
+                for i := uint(0); i < NUM_TABLES-1; i++ {
+                    if  (gen.cellIsReserved(A, schedule, i+1) || gen.cellIsReserved(B, schedule, i+1)) &&
+                        (!gen.cellIsReserved(A, schedule, i) && !gen.cellIsReserved(B, schedule, i)) {
+                            lesson = i
+                            break
+                        }
+                }
+            }
+
+        default:
+            switch {
+            case    lesson > 1 && gen.cellIsReserved(subgroup, schedule, lesson-1) &&
+                    !gen.cellIsReserved(subgroup, schedule, lesson+1): // pass
+            default: 
+                // "Подтягивать" неполные пары к уже существующим [перед].
+                for i := uint(0); i < NUM_TABLES-1; i++ {
+                    if  !gen.cellIsReserved(subgroup, schedule, i) && gen.cellIsReserved(subgroup, schedule, i+1) {
+                            lesson = i
+                            break
+                        }
+                }
+            }
+        }
+
+tryAfter:
+        if isAfter {
+            switch subgroup {
+            case ALL:
+                // "Подтягивать" полные пары к уже существующим [после].
+                for i := uint(0); i < NUM_TABLES-1; i++ {
+                    if  (gen.cellIsReserved(A, schedule, i) || gen.cellIsReserved(B, schedule, i)) &&
+                        (!gen.cellIsReserved(A, schedule, i+1) && !gen.cellIsReserved(B, schedule, i+1)) {
+                            lesson = i+1
+                            break
+                        }
+                }
+            default:
+                // "Подтягивать" неполные пары к уже существующим [после].
+                for i := uint(0); i < NUM_TABLES-1; i++ {
+                    if  (gen.cellIsReserved(ALL, schedule, i) || gen.cellIsReserved(subgroup, schedule, i)) &&
+                        !gen.cellIsReserved(subgroup, schedule, i+1) {
+                            lesson = i+1
+                            break
+                        }
+                }
+            }
+        }
+
+        var (
+            cabinet = ""
+            cabinet2 = ""
+        )
+        // Если ячейка уже зарезервирована или учитель занят, или кабинет зарезервирован, или
+        // если это полная пара и ячейка занята либо первой, либо второй подгруппой, или
+        // если это двойная пара и кабинеты второго учителя зарезервированы, или 
+        // если это двойная пара и второй учитель занят: попытаться сдвинуть пары к уже существующим.
+        // Если не получается, тогда не ставить этот урок.
+        if  gen.cellIsReserved(subgroup, schedule, lesson) || 
+            gen.teacherIsReserved(subject.Teacher, lesson) || 
+            gen.cabinetIsReserved(subgroup, subject, subject.Teacher, lesson, &cabinet) || 
+            (subgroup == ALL && (gen.cellIsReserved(A, schedule, lesson) || gen.cellIsReserved(B, schedule, lesson))) ||
+            (gen.withSubgroups(group.Name) && gen.isDoubleLesson(group.Name, subject.Name) && gen.teacherIsReserved(subject.Teacher2, lesson)) || 
+            (gen.withSubgroups(group.Name) && gen.isDoubleLesson(group.Name, subject.Name) && gen.cabinetIsReserved(subgroup, subject, subject.Teacher2, lesson, &cabinet2)) {
+                if isAfter {
+                    break nextLesson
+                }
+                if lesson != savedLesson {
+                    isAfter = true
+                    goto tryAfter
+                }
+                continue nextLesson
+        }
+
+        // Если существует шаблон расписания, тогда придерживаться его структуры.
+        if template != nil {
+            for _, sch := range template {
+                if sch.Group == group.Name {
+                    if sch.Table[lesson].Subject[A] == "" && sch.Table[lesson].Subject[B] == "" {
+                        if  (gen.cellIsReserved(A, schedule, lesson) && !gen.cellIsReserved(B, schedule, lesson)) ||
+                            (gen.cellIsReserved(B, schedule, lesson) && !gen.cellIsReserved(A, schedule, lesson)) {
+                                break
+                        }
+                        lesson = savedLesson
+                        continue nextLesson
+                    }
+                    break
+                }
+            }
+        }
+
+        // Полный день - максимум 7 пар.
+        // lesson начинается с нуля!
+        if (gen.Day != WEDNESDAY && gen.Day != SATURDAY) && lesson >= 7 {
+            break nextLesson
+        }
+
+        // В среду и субботу - 5-6 пары должны быть свободны.
+        // lesson начинается с нуля!
+        if (gen.Day == WEDNESDAY || gen.Day == SATURDAY) && (lesson == 4 || lesson == 5) {
+            lesson = savedLesson // Возобновить сохранённое занятие.
+            continue nextLesson // Перейти к следующей ячейке.
+        }
+
+        // [ II ] Вторая проверка.
+        switch subgroup {
+        case ALL:
+            // Если уже существует полная пара, которая стоит за парами с подгруппами, тогда
+            // перейти на новую ячейку расписания группы.
+            for i := lesson; i < NUM_TABLES-1; i++ {
+                if  gen.cellIsReserved(A, schedule, i) && !gen.cellIsReserved(B, schedule, i) && gen.cellIsReserved(ALL, schedule, i+1) ||
+                    gen.cellIsReserved(B, schedule, i) && !gen.cellIsReserved(A, schedule, i) && gen.cellIsReserved(ALL, schedule, i+1) {
+                        lesson = savedLesson
+                        continue nextLesson
+                    }
+            }
+        default:
+            // Если у одной подгруппы уже имеется пара, а у второй стоит пара
+            // в это же время, тогда пропустить проверку пустых окон.
+            if  gen.cellIsReserved(A, schedule, lesson) && A != subgroup || 
+                gen.cellIsReserved(B, schedule, lesson) && B != subgroup {
+                    goto passcheck
+            }
+            // Если стоит полная пара, а за ней идёт подгруппа неравная проверяемой, тогда
+            // прекратить ставить пары у проверяемой подгруппы.
+            fullLessons := false
+            for i := uint(0); i < lesson; i++ {
+                if gen.cellIsReserved(ALL, schedule, i) {
+                    fullLessons = true
+                    continue
+                }
+                if  (fullLessons && gen.cellIsReserved(A, schedule, i) && A != subgroup) ||
+                    (fullLessons && gen.cellIsReserved(B, schedule, i) && B != subgroup) {
+                        break nextLesson
+                }
+            }
+        }
+
+passcheck:
+        // [ III ] Третья проверка.
+        // Если нет возможности добавить новые пары без создания окон, тогда не ставить пары.
+        if lesson > 1 {
+            switch subgroup {
+            case ALL:
+                for i := uint(0); i < lesson-1; i++ {
+                    if  (gen.cellIsReserved(A, schedule, i) && !gen.cellIsReserved(A, schedule, lesson-1)) || 
+                        (gen.cellIsReserved(B, schedule, i) && !gen.cellIsReserved(B, schedule, lesson-1)) {
+                            break nextLesson
+                    }
+                }
+            default:
+                for i := uint(0); i < lesson-1; i++ {
+                    if  gen.cellIsReserved(subgroup, schedule, i) && !gen.cellIsReserved(subgroup, schedule, lesson-1) {
+                        break nextLesson
+                    }
+                }
+            }
+        }
+
+        gen.Reserved.Teachers[subject.Teacher][lesson] = true
+        gen.Reserved.Cabinets[cabinet][lesson] = true
+
+        switch subgroup {
+        case A:
+            gen.Groups[group.Name].Subjects[subject.Name].WeekLessons.A -= 1
+            gen.Groups[group.Name].Subjects[subject.Name].Practice.A -= 1
+            countl.A += 1
+        case B:
+            gen.Groups[group.Name].Subjects[subject.Name].WeekLessons.B -= 1
+            gen.Groups[group.Name].Subjects[subject.Name].Practice.B -= 1
+            countl.B += 1
+        case ALL:
+            gen.Groups[group.Name].Subjects[subject.Name].WeekLessons.A -= 1
+            gen.Groups[group.Name].Subjects[subject.Name].WeekLessons.B -= 1
+            countl.A += 1
+            countl.B += 1
+            switch subjtype {
+            case THEORETICAL:
+                gen.Groups[group.Name].Subjects[subject.Name].Theory -= 1
+            case PRACTICAL:
+                gen.Groups[group.Name].Subjects[subject.Name].Practice.A -= 1
+                gen.Groups[group.Name].Subjects[subject.Name].Practice.B -= 1
+            }
+        }
+
+        if subgroup == ALL {
+            schedule.Table[lesson].Teacher = [ALL]string{
+                subject.Teacher,
+                subject.Teacher,
+            }
+            schedule.Table[lesson].Subject = [ALL]string{
+                subject.Name,
+                subject.Name,
+            }
+            schedule.Table[lesson].Cabinet = [ALL]string{
+                cabinet,
+                cabinet,
+            }
+            // Если это двойная пара и группа делимая, тогда поставить пару с разными преподавателями.
+            if gen.isDoubleLesson(group.Name, subject.Name) && gen.withSubgroups(group.Name) {
+                gen.Reserved.Teachers[subject.Teacher2][lesson] = true
+                gen.Reserved.Cabinets[cabinet2][lesson] = true
+                schedule.Table[lesson].Teacher[B] = subject.Teacher2
+                schedule.Table[lesson].Cabinet[B] = cabinet2
+            }
+            lesson = savedLesson
+            continue nextLesson
+        }
+
+        schedule.Table[lesson].Teacher[subgroup] = subject.Teacher
+        schedule.Table[lesson].Subject[subgroup] = subject.Name
+        schedule.Table[lesson].Cabinet[subgroup] = cabinet
+        lesson = savedLesson
+    }
+
+    if template != nil && !flag {
+        flag = true
+        goto startAgain
+    }
+}
+
+func (gen *Generator) isLimitLessons(subgroup SubgroupType, countl *Subgroup) bool {
+    switch subgroup {
+    case ALL:
+        if countl.A >= MAX_COUNT_LESSONS_IN_DAY && countl.B >= MAX_COUNT_LESSONS_IN_DAY {
+            return true
+        }
+    case A:
+        if countl.A >= MAX_COUNT_LESSONS_IN_DAY {
+            return true
+        }
+    case B:
+        if countl.B >= MAX_COUNT_LESSONS_IN_DAY {
+            return true
+        }
+    }
+    return false
+}
+
+func (gen *Generator) withSubgroups(group string) bool {
+    if gen.Groups[group].Quantity > MAX_COUNT_WITHOUT_SUBGROUPS {
+        return true
+    }
+    return false
+}
+
+func (gen *Generator) blockTeacher(teacher string) error {
+    if !gen.inTeachers(teacher) {
+        return errors.New("teacher undefined")
+    }
+    gen.Blocked[teacher] = true
+    return nil
+}
+
+func (gen *Generator) inBlocked(teacher string) bool {
+    if _, ok := gen.Blocked[teacher]; !ok {
+        return false
+    }
+    return true
+}
+
+func (gen *Generator) inGroups(group string) bool {
+    if _, ok := gen.Groups[group]; !ok {
+        return false
+    }
+    return true
+}
+
+func (gen *Generator) inTeachers(teacher string) bool {
+    if _, ok := gen.Teachers[teacher]; !ok {
+        return false
+    }
+    return true
+}
+
+func (gen *Generator) unblockTeacher(teacher string) error {
+    if !gen.inBlocked(teacher) {
+        return errors.New("teacher undefined")
+    }
+    delete(gen.Blocked, teacher)
+    return nil
+}
+
+func packJSON(data interface{}) []byte {
+    jsonData, err := json.MarshalIndent(data, "", "\t")
+    if err != nil {
+        return nil
+    }
+    return jsonData
+}
+
+func unpackJSON(data []byte, output interface{}) error {
+    err := json.Unmarshal(data, output)
+    return err
+}
+
+func writeJSON(filename string, data interface{}) error {
+    return writeFile(filename, string(packJSON(data)))
+}
+
+func (gen *Generator) subjectInGroup(subject string, group string) bool {
+    if !gen.inGroups(group) {
+        return false
+    }
+    if _, ok := gen.Groups[group].Subjects[subject]; !ok {
+        return false
+    }
+    return true
+}
+
+func (gen *Generator) isDoubleLesson(group string, subject string) bool {
+    if !gen.inGroups(group) {
+        return false
+    }
+    if _, ok := gen.Groups[group].Subjects[subject]; !ok {
+        return false
+    }
+    if gen.Groups[group].Subjects[subject].Teacher2 == "" {
+        return false
+    }
+    return true
+}
+
+func shuffle(slice interface{}) interface{}{
+    switch slice.(type) {
+    case []*Group:
+        result := slice.([]*Group)
+        for i := len(result)-1; i > 0; i-- {
+            j := rand.Intn(i+1)
+            result[i], result[j] = result[j], result[i]
+        }
+        return result
+    case []*Subject:
+        result := slice.([]*Subject)
+        for i := len(result)-1; i > 0; i-- {
+            j := rand.Intn(i+1)
+            result[i], result[j] = result[j], result[i]
+        }
+        return result
+    }
+    return nil
+}
+
+func (gen *Generator) cellIsReserved(subgroup SubgroupType, schedule *Schedule, lesson uint) bool {
+    if lesson >= NUM_TABLES {
+        return false
+    }
+    switch subgroup {
+    case A: 
+        if schedule.Table[lesson].Subject[A] != "" {
+            return true
+        }
+    case B:
+        if schedule.Table[lesson].Subject[B] != "" {
+            return true
+        }
+    case ALL:
+        if schedule.Table[lesson].Subject[A] != "" && schedule.Table[lesson].Subject[B] != "" {
+            return true
+        }
+    }
+    return false
+}
+
+func (gen *Generator) cabinetIsReserved(subgroup SubgroupType, subject *Subject, teacher string, lesson uint, cabinet *string) bool {
+    var result = true
+    if !gen.inTeachers(teacher) {
+        return result
+    }
+    for _, cab := range gen.Teachers[teacher].Cabinets {
+        gen.cabinetToReserved(cab.Name)
+        // Если это не компьютерный кабинет, а предмет предполагает практику в компьютерных кабинетах и идёт время практики,
+        // тогда посмотреть другой кабинет преподавателя.
+        if   subject.IsComputer && !cab.IsComputer &&
+             gen.havePracticalLessons(subgroup, subject) &&
+            !gen.haveTheoreticalLessons(subject) {
+                continue
+        }
+        // Если кабинет не зарезирвирован, тогда занять кабинет.
+        if _, ok := gen.Reserved.Cabinets[cab.Name]; ok && !gen.Reserved.Cabinets[cab.Name][lesson] {
+            *cabinet = cab.Name
+            return false
+        }
+    }
+    return result
+}
+
+func (gen *Generator) teacherIsReserved(teacher string, lesson uint) bool {
+    gen.teacherToReserved(teacher)
+    if value, ok := gen.Reserved.Teachers[teacher]; ok {
+        return value[lesson] == true
+    }
+    return false
+}
+
+func (gen *Generator) teacherToReserved(teacher string) {
+    if _, ok := gen.Reserved.Teachers[teacher]; ok {
+        return
+    }
+    gen.Reserved.Teachers[teacher] = make([]bool, NUM_TABLES)
+}
+
+func (gen *Generator) cabinetToReserved(cabnum string) {
+    if _, ok := gen.Reserved.Cabinets[cabnum]; ok {
+        return
+    }
+    gen.Reserved.Cabinets[cabnum] = make([]bool, NUM_TABLES)
+}
+
+func (gen *Generator) notHaveWeekLessons(subgroup SubgroupType, subject *Subject) bool {
+    switch subgroup {
+    case A:
+        if subject.WeekLessons.A == 0 {
+            return true
+        }
+    case B:
+        if subject.WeekLessons.B == 0 {
+            return true
+        }
+    case ALL:
+        if subject.WeekLessons.A == 0 && subject.WeekLessons.B == 0 {
+            return true
+        }
+    }
+    return false
+}
+
+func (gen *Generator) haveTheoreticalLessons(subject *Subject) bool {
+    if subject.Theory == 0 {
+        return false
+    }
+    return true
+}
+
+func (gen *Generator) havePracticalLessons(subgroup SubgroupType, subject *Subject) bool {
+    switch subgroup {
+    case A:
+        if subject.Practice.A == 0 {
+            return false
+        }
+    case B:
+        if subject.Practice.B == 0 {
+            return false
+        }
+    case ALL:
+        if subject.Practice.A == 0 && subject.Practice.B == 0 {
+            return false
+        }
+    }
+    return true
+}
+
+func getGroups(groups map[string]*Group) []*Group {
+    var list []*Group
+    for _, group := range groups {
+        list = append(list, group)
+    }
+    return shuffle(list).([]*Group)
+}
+
+func getSubjects(subjects map[string]*Subject) []*Subject {
+    var list []*Subject
+    for _, subject := range subjects {
+        list = append(list, subject)
+    }
+    return shuffle(list).([]*Subject)
+}
+
+func sortSchedule(schedule []*Schedule) []*Schedule {
+    sort.SliceStable(schedule, func(i, j int) bool {
+        return schedule[i].Group < schedule[j].Group
+    })
+    return schedule
+}
+
+func colWidthForCabinets(index int) (int, int, float64) {
+    var col = (index+1)*3+1
+    return col, col, COL_W_CAB
+}
+
+// Returns [min:max] value.
+func random(min, max int) int {
+    return rand.Intn(max - min + 1) + min
+}
+
+func readFile(filename string) string {
+    file, err := os.Open(filename)
+    if err != nil {
+        return ""
+    }
+    defer file.Close()
+
+    var (
+        buffer []byte = make([]byte, BUFFER)
+        data string
+    )
+
+    for {
+        length, err := file.Read(buffer)
+        if length == 0 || err != nil { break }
+        data += string(buffer[:length])
+    }
+
+    return data
+}
+
+func writeFile(filename, data string) error {
+    file, err := os.Create(filename)
+    if err != nil {
+        return err
+    }
+    file.WriteString(data)
+    file.Close()
+    return nil
+}

+ 102 - 0
schedule/models.go

@@ -0,0 +1,102 @@
+package schedule
+
+type DayType uint8
+const (
+	SUNDAY 		DayType = 0
+	MONDAY 		DayType = 1
+	TUESDAY 	DayType = 2
+	WEDNESDAY 	DayType = 3
+	THURSDAY 	DayType = 4
+	FRIDAY 		DayType = 5
+	SATURDAY 	DayType = 6
+)
+
+type SubgroupType uint8
+const (
+	A 	SubgroupType = 0
+	B 	SubgroupType = 1
+	ALL SubgroupType = 2
+)
+
+type SubjectType uint8
+const (
+	THEORETICAL	SubjectType = 0
+	PRACTICAL 	SubjectType = 1
+)
+
+type Generator struct {
+	Day DayType
+	Debug bool
+	Groups map[string]*Group
+	Teachers map[string]*Teacher
+	Blocked map[string]bool
+	Reserved Reserved
+}
+
+type Reserved struct {
+	Teachers map[string][]bool
+	Cabinets map[string][]bool
+}
+
+type Schedule struct {
+	Day DayType
+	Group string
+	Table []Row
+}
+
+type Row struct {
+	Subject [ALL]string
+	Teacher [ALL]string
+	Cabinet [ALL]string
+}
+
+type Teacher struct {
+	Name string `json:"name"`
+	Cabinets []Cabinet `json:"cabinets"`
+}
+
+type Cabinet struct {
+	Name string `json:"name"`
+	IsComputer bool `json:"is_computer"`
+}
+
+type Group struct {
+	Name string
+	Quantity uint // students count
+	Subjects map[string]*Subject
+}
+
+type Subject struct {
+	Name string
+	Teacher string
+	Teacher2 string
+	IsComputer bool
+	SaveWeek uint
+	Theory uint
+	Practice Subgroup
+	WeekLessons Subgroup
+}
+
+type Subgroup struct {
+	A uint
+	B uint
+}
+
+type GroupJSON struct {
+	Name string `json:"name"`
+	Quantity uint `json:"quantity"`
+	Subjects []SubjectJSON `json:"subjects"`
+}
+
+type SubjectJSON struct {
+	Name string `json:"name"`
+	Teacher string `json:"teacher"`
+	IsComputer bool `json:"is_computer"`
+	Lessons LessonsJSON `json:"lessons"`
+}
+
+type LessonsJSON struct {
+	Theory uint `json:"theory"`
+	Practice uint `json:"practice"`
+	Week uint `json:"week"`
+}

+ 18 - 0
schedule/settings.go

@@ -0,0 +1,18 @@
+package schedule
+
+const (
+	BUFFER = 1 << 20 // 1MiB
+)
+
+const (
+	NUM_TABLES = 11
+	MAX_COUNT_LESSONS_IN_DAY = 3
+	MAX_COUNT_WITHOUT_SUBGROUPS = 16
+)
+
+// For XLSX.
+const (
+	ROW_H = 30
+	COL_W = 30
+	COL_W_CAB = 10
+)

+ 29 - 0
settings/settings.go

@@ -0,0 +1,29 @@
+package settings
+
+import "github.com/jinzhu/gorm"
+
+var DB *gorm.DB
+
+const (
+	TimeLayout = "15:04"
+	dateLayout = ""
+	login      = "dbuser"
+	password   = "QWEasd123"
+	ipaddr     = "192.168.10.14"
+	port       = "3306"
+	dbname     = "Schedule"
+	protocol   = "tcp"
+	args       = "parseTime=true&charset=utf8&loc=Local"
+	CONSTR     = login + ":" + password + "@" + protocol + "(" + ipaddr + ":" + port + ")/" + dbname + "?" + args
+	// clientLDAP= &ldap.LDAPClient{
+	// 	Base:         "dc=ttit,dc=local",
+	// 	Host:         "ttit.local",
+	// 	Port:         389,
+	// 	UseSSL:       false,
+	// 	BindDN:       "uid=User,ou=People,dc=ttit,dc=local",
+	// 	BindPassword: "Password",
+	// 	UserFilter:   "(uid=%s)",
+	// 	GroupFilter: "(memberUid=%s)",
+	// 	Attributes:   []string{"givenName", "sn", "mail", "uid"},
+	// }
+)

二進制
static/assets/banners/default_300x250.jpg


二進制
static/assets/banners/default_300x600.jpg


二進制
static/assets/banners/default_728x90.jpg


+ 64 - 0
static/assets/email/action.html

@@ -0,0 +1,64 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <meta name="viewport" content="width=device-width">
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+        <title>Actionable emails e.g. reset password</title>
+        <link href="styles.css" media="all" rel="stylesheet" type="text/css">
+    </head>
+
+    <body itemscope itemtype="http://schema.org/EmailMessage">
+
+        <table class="body-wrap">
+            <tr>
+                <td></td>
+                <td class="container" width="600">
+                    <div class="content">
+                        <table class="main" width="100%" cellpadding="0" cellspacing="0" itemprop="action" itemscope itemtype="http://schema.org/ConfirmAction">
+                            <tr>
+                                <td class="logo">
+                                    <img src="logo.png">
+                                </td>
+                            </tr>
+                            <tr>                                
+                                <td class="content-wrap">
+                                    <meta itemprop="name" content="Confirm Email"/>
+                                    <table width="100%" cellpadding="0" cellspacing="0">
+                                        <tr>
+                                            <td class="content-block">
+                                                Please confirm your email address by clicking the link below.
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td class="content-block">
+                                                We may need to send you critical information about our service and it is important that we have an accurate email address.
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td class="content-block" itemprop="handler" itemscope itemtype="http://schema.org/HttpActionHandler">
+                                                <a href="#" class="btn-primary" itemprop="url">Confirm email address</a>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td class="content-block">
+                                                &mdash; The Mailgunners
+                                            </td>
+                                        </tr>
+                                    </table>
+                                </td>
+                            </tr>
+                        </table>
+                        <div class="footer">
+                            <table width="100%">
+                                <tr>
+                                    <td class="aligncenter content-block">Follow <a href="#">Boooya</a> on Twitter.</td>
+                                </tr>
+                            </table>
+                        </div></div>
+                </td>
+                <td></td>
+            </tr>
+        </table>
+
+    </body>
+</html>

+ 68 - 0
static/assets/email/alert.html

@@ -0,0 +1,68 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+        <meta name="viewport" content="width=device-width">
+        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+        <title>Alerts e.g. approaching your limit</title>
+        <link href="styles.css" media="all" rel="stylesheet" type="text/css">
+    </head>
+
+    <body itemscope itemtype="http://schema.org/EmailMessage">
+
+        <table class="body-wrap">
+            <tr>
+                <td></td>
+                <td class="container" width="600">
+                    <div class="content">
+                        <table class="main" width="100%" cellpadding="0" cellspacing="0">
+                            <tr>
+                                <td class="logo">
+                                    <img src="logo.png">
+                                </td>
+                            </tr>
+                            <tr>
+                                <td class="alert alert-warning">
+                                    Warning: You're approaching your limit. Please upgrade.
+                                </td>
+                            </tr>
+                            <tr>
+                                <td class="content-wrap">
+                                    <table width="100%" cellpadding="0" cellspacing="0">
+                                        <tr>
+                                            <td class="content-block">
+                                                You have <strong>1 free report</strong> remaining.
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td class="content-block">
+                                                Add your credit card now to upgrade your account to a premium plan to ensure you don't miss out on any reports.
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td class="content-block">
+                                                <a href="#" class="btn-primary">Upgrade my account</a>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td class="content-block">
+                                                Thanks for choosing Boooya Inc.
+                                            </td>
+                                        </tr>
+                                    </table>
+                                </td>
+                            </tr>
+                        </table>
+                        <div class="footer">
+                            <table width="100%">
+                                <tr>
+                                    <td class="aligncenter content-block"><a href="#">Unsubscribe</a> from these alerts.</td>
+                                </tr>
+                            </table>
+                        </div></div>
+                </td>
+                <td></td>
+            </tr>
+        </table>
+
+    </body>
+</html>

+ 95 - 0
static/assets/email/billing.html

@@ -0,0 +1,95 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta name="viewport" content="width=device-width">
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <title>Billing e.g. invoices and receipts</title>
+    <link href="styles.css" media="all" rel="stylesheet" type="text/css">
+</head>
+
+    <body itemscope itemtype="http://schema.org/EmailMessage">
+
+        <table class="body-wrap">
+            <tr>
+                <td></td>
+                <td class="container" width="600">
+                    <div class="content">
+                        <table class="main" width="100%" cellpadding="0" cellspacing="0">
+                            <tr>
+                                <td class="logo">
+                                    <img src="logo.png">
+                                </td>
+                            </tr>
+                            <tr>
+                                <td class="content-wrap aligncenter">
+                                    <table width="100%" cellpadding="0" cellspacing="0">
+                                        <tr>
+                                            <td class="content-block">
+                                                <h1 class="aligncenter">$33.98 Paid</h1>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td class="content-block">
+                                                <h2 class="aligncenter">Thanks for using Boooya.</h2>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td class="content-block aligncenter">
+                                                <table class="invoice">
+                                                    <tr>
+                                                        <td>Lee Munroe<br>Invoice #12345<br>June 01 2014</td>
+                                                    </tr>
+                                                    <tr>
+                                                        <td>
+                                                            <table class="invoice-items" cellpadding="0" cellspacing="0">
+                                                                <tr>
+                                                                    <td>Service 1</td>
+                                                                    <td class="alignright">$ 19.99</td>
+                                                                </tr>
+                                                                <tr>
+                                                                    <td>Service 2</td>
+                                                                    <td class="alignright">$ 9.99</td>
+                                                                </tr>
+                                                                <tr>
+                                                                    <td>Service 3</td>
+                                                                    <td class="alignright">$ 4.00</td>
+                                                                </tr>
+                                                                <tr class="total">
+                                                                    <td class="alignright" width="80%">Total</td>
+                                                                    <td class="alignright">$ 33.98</td>
+                                                                </tr>
+                                                            </table>
+                                                        </td>
+                                                    </tr>
+                                                </table>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td class="content-block aligncenter">
+                                                <a href="http://www.mailgun.com">View in browser</a>
+                                            </td>
+                                        </tr>
+                                        <tr>
+                                            <td class="content-block aligncenter">
+                                                Boooya Inc. 123 Van Ness, San Francisco 94102
+                                            </td>
+                                        </tr>
+                                    </table>
+                                </td>
+                            </tr>
+                        </table>
+                        <div class="footer">
+                            <table width="100%">
+                                <tr>
+                                    <td class="aligncenter content-block">Questions? Email <a href="#">support@boooya.com</a></td>
+                                </tr>
+                            </table>
+                        </div>
+                    </div>
+                </td>
+                <td></td>
+            </tr>
+        </table>
+
+    </body>
+</html>

二進制
static/assets/email/logo.png


二進制
static/assets/email/preview/action.png


二進制
static/assets/email/preview/alert.png


二進制
static/assets/email/preview/billing.png


+ 288 - 0
static/assets/email/styles.css

@@ -0,0 +1,288 @@
+/* -------------------------------------
+    GLOBAL
+    A very basic CSS reset
+------------------------------------- */
+* {
+  margin: 0;
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  box-sizing: border-box;
+  font-size: 14px;
+}
+
+img {
+  max-width: 100%;
+}
+
+body {
+  -webkit-font-smoothing: antialiased;
+  -webkit-text-size-adjust: none;
+  width: 100% !important;
+  height: 100%;
+  line-height: 1.6em;
+  /* 1.6em * 14px = 22.4px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
+  /*line-height: 22px;*/
+}
+
+/* Let's make sure all tables have defaults */
+table td {
+  vertical-align: top;
+}
+
+/* -------------------------------------
+    BODY & CONTAINER
+------------------------------------- */
+body {
+  background-color: #f6f6f6;
+}
+
+.body-wrap {
+  background-color: #f6f6f6;
+  width: 100%;
+}
+
+.container {
+  display: block !important;
+  max-width: 600px !important;
+  margin: 0 auto !important;
+  /* makes it centered */
+  clear: both !important;
+}
+
+.content {
+  max-width: 600px;
+  margin: 0 auto;
+  display: block;
+  padding: 20px;
+}
+
+/* -------------------------------------
+    HEADER, FOOTER, MAIN
+------------------------------------- */
+.main {
+  background-color: #fff;
+  border: 1px solid #DBE0E4;
+  border-radius: 3px;
+}
+
+.content-wrap {
+  padding: 20px;
+}
+
+.content-block {
+  padding: 0 0 20px;
+}
+
+.header {
+  width: 100%;
+  margin-bottom: 20px;
+}
+
+.footer {
+  width: 100%;
+  clear: both;
+  color: #7F8FA4;
+  padding: 20px;
+}
+.footer p, .footer a, .footer td {
+  color: #999;
+  font-size: 12px;
+}
+
+/* -------------------------------------
+    TYPOGRAPHY
+------------------------------------- */
+h1, h2, h3 {
+  font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
+  color: #1B2431;
+  margin: 40px 0 0;
+  line-height: 1.2em;
+  font-weight: 400;
+}
+
+h1 {
+  font-size: 32px;
+  font-weight: 500;
+  /* 1.2em * 32px = 38.4px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
+  /*line-height: 38px;*/
+}
+
+h2 {
+  font-size: 24px;
+  /* 1.2em * 24px = 28.8px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
+  /*line-height: 29px;*/
+}
+
+h3 {
+  font-size: 18px;
+  /* 1.2em * 18px = 21.6px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
+  /*line-height: 22px;*/
+}
+
+h4 {
+  font-size: 14px;
+  font-weight: 600;
+}
+
+p, ul, ol {
+  margin-bottom: 10px;
+  font-weight: normal;
+}
+p li, ul li, ol li {
+  margin-left: 5px;
+  list-style-position: inside;
+}
+
+/* -------------------------------------
+    LINKS & BUTTONS
+------------------------------------- */
+a {
+  color: #0F9DEA;
+  text-decoration: underline;
+}
+
+.btn-primary {
+  text-decoration: none;
+  color: #FFF;
+  background-color: #2D3349;
+  border: solid #2D3349;
+  border-width: 10px 20px;
+  line-height: 2em;
+  /* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
+  /*line-height: 28px;*/
+  font-weight: bold;
+  text-align: center;
+  cursor: pointer;
+  display: inline-block;
+  border-radius: 5px;
+  text-transform: capitalize;
+}
+
+/* -------------------------------------
+    OTHER STYLES THAT MIGHT BE USEFUL
+------------------------------------- */
+.last {
+  margin-bottom: 0;
+}
+
+.first {
+  margin-top: 0;
+}
+
+.aligncenter {
+  text-align: center;
+}
+
+.alignright {
+  text-align: right;
+}
+
+.alignleft {
+  text-align: left;
+}
+
+.clear {
+  clear: both;
+}
+
+.logo{
+    background: #2D3349;
+    text-align: center;
+    border-radius: 3px 3px 0 0;
+    padding: 40px 0px;
+}
+
+/* -------------------------------------
+    ALERTS
+    Change the class depending on warning email, good email or bad email
+------------------------------------- */
+.alert {
+  font-size: 14px;  
+  color: #fff;
+  font-weight: 500;  
+  padding: 20px;
+  text-align: center;  
+}
+.alert a {
+  color: #fff;
+  text-decoration: none;
+  font-weight: 500;
+  font-size: 16px;
+}
+.alert.alert-warning {
+  background-color: #e55701;
+}
+.alert.alert-bad {
+  background-color: #D0021B;
+}
+.alert.alert-good {
+  background-color: #68B90F;
+}
+
+/* -------------------------------------
+    INVOICE
+    Styles for the billing table
+------------------------------------- */
+.invoice {
+  margin: 40px auto;
+  text-align: left;
+  width: 80%;
+}
+.invoice td {
+  padding: 5px 0;
+}
+.invoice .invoice-items {
+  width: 100%;
+}
+.invoice .invoice-items td {
+  border-top: #eee 1px solid;
+}
+.invoice .invoice-items .total td {
+  border-top: 2px solid #333;
+  border-bottom: 2px solid #333;
+  font-weight: 700;
+}
+
+/* -------------------------------------
+    RESPONSIVE AND MOBILE FRIENDLY STYLES
+------------------------------------- */
+@media only screen and (max-width: 640px) {
+  body {
+    padding: 0 !important;
+  }
+
+  h1, h2, h3, h4 {
+    font-weight: 800 !important;
+    margin: 20px 0 5px !important;
+  }
+
+  h1 {
+    font-size: 22px !important;
+  }
+
+  h2 {
+    font-size: 18px !important;
+  }
+
+  h3 {
+    font-size: 16px !important;
+  }
+
+  .container {
+    padding: 0 !important;
+    width: 100% !important;
+  }
+
+  .content {
+    padding: 0 !important;
+  }
+
+  .content-wrap {
+    padding: 10px !important;
+  }
+
+  .invoice {
+    width: 100% !important;
+  }
+}
+
+/*# sourceMappingURL=styles.css.map */

二進制
static/assets/header/header-1.jpg


二進制
static/assets/header/header-2.jpg


文件差異過大導致無法顯示
+ 1 - 0
static/assets/html/calendar_ajax.html


+ 58 - 0
static/assets/html/preview_ajax.html

@@ -0,0 +1,58 @@
+<div class="app-heading app-heading-small app-heading-condensed">                                
+    <div class="title">
+        <h2>Ajax</h2>
+        <p>This content is loaded using ajax</p>
+    </div>                                
+</div>
+
+<div class="form-group">    
+    <div class="col-md-6">
+        <label>Text</label>
+        <input type="text" class="form-control" name="input-1" placeholder="Input Text #1">
+    </div>
+    <div class="col-md-6">
+        <label>Password</label>
+        <input type="password" class="form-control" name="input-1" placeholder="Input Password #2">
+</div>
+<div class="form-group margin-top-20">
+    <div class="col-md-6">
+        <label>Datepicker</label>
+        <input type="text" class="form-control bs-datepicker" name="dapicker">
+    </div>
+    <div class="col-md-6">
+        <label>Select</label>
+        <select class="bs-select" multiple="">
+            <optgroup label="Group 1-2" data-max-options="1">
+                <option>Option Number 1</option>
+                <option>Option Number 2</option>
+            </optgroup>
+            <optgroup label="Group 3-5" data-max-options="2">
+                <option>Option Number 3</option>
+                <option>Option Number 4</option>                                        
+                <option>Option Number 5</option>                                        
+            </optgroup>                                        
+        </select>
+</div>
+<div class="form-group margin-top-20">
+    <div class="col-md-4">
+        <label>Checkbox</label>
+        <div class="app-checkbox"> 
+            <label><input type="checkbox" name="app-checkbox-1" value="0"> Default Checkbox</label> 
+        </div>                                    
+    </div>
+    <div class="col-md-4">
+        <label>Radio 1</label>
+        <div class="app-radio"> 
+            <label><input type="radio" name="app-radio-1" value="0"> Default Radio</label> 
+        </div>                                    
+    </div>
+    <div class="col-md-4">
+        <label>Radio 2</label>
+        <div class="app-radio"> 
+            <label><input type="radio" name="app-radio-1" value="1" checked> Checked Radio</label> 
+        </div>
+    </div>    
+</div>
+<div class="form-group text-right">
+    <button class="btn btn-default" data-dismiss="modal">Close</button>
+</div>

二進制
static/assets/images/background/bg-1.jpg


二進制
static/assets/images/landing/header_background.fw.png


二進制
static/assets/images/landing/header_background.jpg


二進制
static/assets/images/landing/layouts.png


二進制
static/assets/images/landing/presentation.png


二進制
static/assets/images/landing/responsive.png


二進制
static/assets/images/large/img-1.jpg


二進制
static/assets/images/large/img-10.jpg


二進制
static/assets/images/large/img-11.jpg


二進制
static/assets/images/large/img-12.jpg


二進制
static/assets/images/large/img-2.jpg


二進制
static/assets/images/large/img-3.jpg


二進制
static/assets/images/large/img-4.jpg


二進制
static/assets/images/large/img-5.jpg


二進制
static/assets/images/large/img-6.jpg


二進制
static/assets/images/large/img-7.jpg


二進制
static/assets/images/large/img-8.jpg


二進制
static/assets/images/large/img-9.jpg


二進制
static/assets/images/news/business_1.jpg


二進制
static/assets/images/news/business_2.jpg


二進制
static/assets/images/news/business_3.jpg


二進制
static/assets/images/news/city_1.jpg


+ 0 - 0
static/assets/images/news/city_2.jpg


部分文件因文件數量過多而無法顯示