generator.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package schedule
  2. import (
  3. "fmt"
  4. "encoding/json"
  5. "github.com/tealeg/xlsx"
  6. )
  7. func NewGenerator(data *Generator) *Generator {
  8. return &Generator{
  9. Day: data.Day,
  10. Debug: data.Debug,
  11. Groups: data.Groups,
  12. Teachers: data.Teachers,
  13. Cabinets: data.Cabinets,
  14. // Blocked: make(map[string]bool),
  15. Reserved: Reserved{
  16. Teachers: make(map[string][]bool),
  17. Cabinets: make(map[string][]bool),
  18. },
  19. }
  20. }
  21. func (gen *Generator) NewSchedule(group string) *Schedule {
  22. return &Schedule{
  23. Day: gen.Day,
  24. Group: group,
  25. Table: make([]Row, NUM_TABLES),
  26. }
  27. }
  28. func ReadGroups(filename string) map[string]*Group {
  29. var (
  30. groups = make(map[string]*Group)
  31. groupsList []GroupJSON
  32. )
  33. data := readFile(filename)
  34. err := json.Unmarshal([]byte(data), &groupsList)
  35. if err != nil {
  36. return nil
  37. }
  38. for _, gr := range groupsList {
  39. groups[gr.Name] = &Group{
  40. Name: gr.Name,
  41. Quantity: gr.Quantity,
  42. }
  43. groups[gr.Name].Subjects = make(map[string]*Subject)
  44. for _, sb := range gr.Subjects {
  45. if _, ok := groups[gr.Name].Subjects[sb.Name]; ok {
  46. groups[gr.Name].Subjects[sb.Name].Teacher2 = sb.Teacher
  47. continue
  48. }
  49. groups[gr.Name].Subjects[sb.Name] = &Subject{
  50. Name: sb.Name,
  51. Teacher: sb.Teacher,
  52. IsComputer: sb.IsComputer,
  53. SaveWeek: sb.Lessons.Week,
  54. Lessons: Lessons{
  55. Theory: sb.Lessons.Theory,
  56. Practice: Subgroup{
  57. A: sb.Lessons.Practice,
  58. B: sb.Lessons.Practice,
  59. },
  60. Week: Subgroup{
  61. A: sb.Lessons.Week,
  62. B: sb.Lessons.Week,
  63. },
  64. },
  65. }
  66. }
  67. }
  68. return groups
  69. }
  70. func ReadTeachers(filename string) map[string]*Teacher {
  71. var (
  72. teachers = make(map[string]*Teacher)
  73. teachersList []Teacher
  74. )
  75. data := readFile(filename)
  76. err := json.Unmarshal([]byte(data), &teachersList)
  77. if err != nil {
  78. return nil
  79. }
  80. for _, tc := range teachersList {
  81. teachers[tc.Name] = &Teacher{
  82. Name: tc.Name,
  83. Cabinets: tc.Cabinets,
  84. }
  85. }
  86. return teachers
  87. }
  88. func ReadCabinets(filename string) map[string]*Cabinet {
  89. var (
  90. cabinets = make(map[string]*Cabinet)
  91. cabinetsList []Cabinet
  92. )
  93. data := readFile(filename)
  94. err := json.Unmarshal([]byte(data), &cabinetsList)
  95. if err != nil {
  96. return nil
  97. }
  98. for _, cb := range cabinetsList {
  99. cabinets[cb.Name] = &Cabinet{
  100. Name: cb.Name,
  101. IsComputer: cb.IsComputer,
  102. }
  103. }
  104. return cabinets
  105. }
  106. const (
  107. OUTDATA = "output/"
  108. )
  109. func (gen *Generator) Template() [][]*Schedule {
  110. var (
  111. weekLessons = make([][]*Schedule, 7)
  112. generator = new(Generator)
  113. file *xlsx.File
  114. name string
  115. )
  116. unpackJSON(packJSON(gen), generator)
  117. if gen.Debug {
  118. file, name = CreateXLSX(OUTDATA + "template.xlsx")
  119. }
  120. day := generator.Day
  121. for i := day; i < day+7; i++ {
  122. weekLessons[i % 7] = generator.Generate(nil)
  123. if gen.Debug {
  124. generator.WriteXLSX(
  125. file,
  126. name,
  127. weekLessons[i % 7],
  128. int(i % 7),
  129. )
  130. }
  131. }
  132. return weekLessons
  133. }
  134. func (gen *Generator) Generate(template [][]*Schedule) []*Schedule {
  135. var (
  136. list []*Schedule
  137. templt []*Schedule
  138. groups = getGroups(gen.Groups)
  139. )
  140. if template == nil {
  141. templt = nil
  142. } else {
  143. templt = template[gen.Day]
  144. }
  145. for _, group := range groups {
  146. var (
  147. schedule = gen.NewSchedule(group.Name)
  148. subjects = getSubjects(group.Subjects)
  149. countLessons = new(Subgroup)
  150. )
  151. if gen.Day == SUNDAY {
  152. list = append(list, schedule)
  153. for _, subject := range subjects {
  154. saved := gen.Groups[group.Name].Subjects[subject.Name].SaveWeek
  155. gen.Groups[group.Name].Subjects[subject.Name].Lessons.Week.A = saved
  156. gen.Groups[group.Name].Subjects[subject.Name].Lessons.Week.B = saved
  157. }
  158. continue
  159. }
  160. for _, subject := range subjects {
  161. switch {
  162. case gen.haveTheoreticalLessons(subject):
  163. if gen.Debug {
  164. fmt.Println(group.Name, subject.Name, ": not splited THEORETICAL;")
  165. }
  166. gen.tryGenerate(ALL, THEORETICAL, group, subject, schedule, countLessons, templt)
  167. // Практические пары начинаются только после завершения всех теоретических.
  168. default:
  169. // Если подгруппа неделимая, тогда провести практику в виде полной пары.
  170. // Иначе разделить практику на две подгруппы.
  171. if !gen.withSubgroups(group.Name) {
  172. if gen.Debug {
  173. fmt.Println(group.Name, subject.Name, ": not splited PRACTICAL;")
  174. }
  175. gen.tryGenerate(ALL, PRACTICAL, group, subject, schedule, countLessons, templt)
  176. } else {
  177. switch RandSubgroup() {
  178. case A:
  179. if gen.Debug {
  180. fmt.Println(group.Name, subject.Name, ": splited (A -> B);")
  181. }
  182. gen.tryGenerate(A, PRACTICAL, group, subject, schedule, countLessons, templt)
  183. gen.tryGenerate(B, PRACTICAL, group, subject, schedule, countLessons, templt)
  184. case B:
  185. if gen.Debug {
  186. fmt.Println(group.Name, subject.Name, ": splited (B -> A);")
  187. }
  188. gen.tryGenerate(B, PRACTICAL, group, subject, schedule, countLessons, templt)
  189. gen.tryGenerate(A, PRACTICAL, group, subject, schedule, countLessons, templt)
  190. }
  191. }
  192. }
  193. }
  194. list = append(list, schedule)
  195. }
  196. gen.Reserved.Teachers = make(map[string][]bool)
  197. gen.Reserved.Cabinets = make(map[string][]bool)
  198. gen.Day = (gen.Day + 1) % 7
  199. return sortSchedule(list)
  200. }
  201. func RandSubgroup() SubgroupType {
  202. return SubgroupType(random(0, 1))
  203. }
  204. func Load(filename string) *Generator {
  205. var generator = new(Generator)
  206. jsonData := readFile(filename)
  207. err := json.Unmarshal([]byte(jsonData), generator)
  208. if err != nil {
  209. return nil
  210. }
  211. return generator
  212. }
  213. func (gen *Generator) Dump(filename string) error {
  214. return writeJSON(filename, gen)
  215. }