schild.rb 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. require 'schild/version'
  2. require 'sequel'
  3. # String und Symbol werden um snake_case ergänzt, das die Schild-Tabellen umbenennt
  4. module CoreExtensions
  5. module String
  6. def snake_case
  7. return downcase if match(/\A[A-Z]+\z/)
  8. gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
  9. gsub(/([a-z])([A-Z])/, '\1_\2').
  10. downcase
  11. end
  12. end
  13. module Symbol
  14. def snake_case
  15. to_s.snake_case
  16. end
  17. end
  18. end
  19. # Schild hat teilweise nil in DB-Feldern. SchildTypeSaver gibt entweder einen
  20. # "Fehlt"-String zurück oder bei strftime das 1899 Datum zurück.
  21. module SchildTypeSaver
  22. Symbol.include CoreExtensions::Symbol
  23. String.include CoreExtensions::String
  24. # bei include wird für jede Spalte in der Schild-Tabelle eine Ersatzmethode
  25. # erstellt, die bei nil ein Null-Objekt erstellt.
  26. def self.included(klass)
  27. klass.columns.each do |column|
  28. name = column.snake_case
  29. define_method(name) { public_send(column) || Null.new("")}
  30. end
  31. end
  32. class Null < String
  33. def strftime(args)
  34. Time.new("1899").strftime(args)
  35. end
  36. end
  37. end
  38. # Das Schild Modul, das alle Klassen für die Datenbankanbindung bereitstellt
  39. module Schild
  40. # ist die Datenbank-Verbindung. Alle Daten können über diese Konstante abgerufen werden
  41. DB = Sequel.connect(:adapter=>ENV['S_ADAPTER'], :host=>ENV['S_HOST'], :user=>ENV['S_USER'], :password=>ENV['S_PASSWORD'], :database=>ENV['S_DB'])
  42. # Stellt eine Verbindung zu einem Schild-Server her. Sollte nur aufgerufen werden, wenn wechselnde Verbindungen nötig sind.
  43. def self.connect
  44. Sequel.connect(:adapter=>ENV['S_ADAPTER'], :host=>ENV['S_HOST'], :user=>ENV['S_USER'], :password=>ENV['S_PASSWORD'], :database=>ENV['S_DB'])
  45. end
  46. # Stellt die Schüler-Tabelle samt Assoziationen bereit.
  47. class Schueler < Sequel::Model(:schueler)
  48. include SchildTypeSaver
  49. many_to_one :fachklasse, :class => :Fachklasse, :key => :Fachklasse_ID
  50. one_to_many :abschnitte, :class => :Abschnitt
  51. # gibt das z.Zt. aktuelle Halbjahr zurück.
  52. def akt_halbjahr
  53. abschnitte.last
  54. end
  55. # gibt das erste Halbjahr von +jahr+ zurück.
  56. def erstes_halbjahr(jahr)
  57. halbjahr(jahr, 1)
  58. end
  59. # gibt das zweite Halbjahr von +jahr+ zurück.
  60. def zweites_halbjahr(jahr)
  61. halbjahr(jahr, 2)
  62. end
  63. # gibt aus +jahr+ das Halbjahr +1+ oder +2+ zurück.
  64. def halbjahr(jahr, abschnitt)
  65. abschnitte_dataset.where(:jahr => jahr, :abschnitt => abschnitt).first
  66. end
  67. # gibt +Herr+ oder +Frau+ als Anrede für Schüler zurück.
  68. def anrede
  69. if self.Geschlecht == 3
  70. return "Herr"
  71. elsif self.Geschlecht == 4
  72. return "Frau"
  73. end
  74. end
  75. # gibt +true+ zurück, wenn Schüler volljährig.
  76. def volljaehrig?
  77. self.Volljaehrig == "+"
  78. end
  79. # gibt das aktuelle Schuljahr als String im Format "2014/15" zurück.
  80. def schuljahr
  81. jahr = self.AktSchuljahr
  82. "#{jahr}/#{jahr-1999}"
  83. end
  84. end
  85. # Dient als Assoziation für Schüler und deren Klassenbezeichnung etc.
  86. class Fachklasse < Sequel::Model(:eigeneschule_fachklassen)
  87. include SchildTypeSaver
  88. one_to_one :schueler
  89. end
  90. # Assoziation für Lehrer, hauptsächlich für Klassenlehrer
  91. class Klassenlehrer < Sequel::Model(:k_lehrer)
  92. include SchildTypeSaver
  93. one_to_one :abschnitt, :primary_key=>:Kuerzel, :key=>:KlassenLehrer
  94. end
  95. # Ist die Assoziation, die Halbjahre, sog. Abschnitte zurückgibt.
  96. class Abschnitt < Sequel::Model(:schuelerlernabschnittsdaten)
  97. include SchildTypeSaver
  98. many_to_one :schueler, :class => :Schueler, :key => :Schueler_ID
  99. one_to_many :noten, :class => :Noten
  100. many_to_one :klassenlehrer, :class => :Klassenlehrer, :primary_key=>:Kuerzel, :key=>:KlassenLehrer
  101. dataset_module do
  102. # filtert den Datensatz nach Jahr
  103. def jahr(i)
  104. where(:Jahr => i)
  105. end
  106. # filtert den Datensatz nach Halbjahr
  107. def halbjahr(i,j)
  108. jahr(i).where(:Abschnitt => j)
  109. end
  110. # filtert und gibt den Datensatz als Abschnitt des aktuellen Halbjahrs zurück
  111. def akt_halbjahr
  112. halbjahr(Time.new.year-1, 1).first
  113. end
  114. end
  115. # Hilfsmethode für die folgenden Methoden
  116. def faecher_nach_id(id)
  117. noten.sort_by{ |n| n.fach.SortierungS2 }.select{ |n| n.fach.Fachgruppe_ID == id && n.AufZeugnis == '+' }
  118. end
  119. # wählt alle berufsübergreifenden Fächer des gewählten Schülers in angegeben Halbjahr.
  120. def berufsuebergreifend
  121. faecher_nach_id 10
  122. end
  123. # wählt alle berufsbezogenen Fächer des gewählten Schülers in angegeben Halbjahr.
  124. def berufsbezogen
  125. faecher_nach_id 20
  126. end
  127. # wählt alle Fächer des Differenzierungsbreichs des gewählten Schülers in angegeben Halbjahr.
  128. def differenzierungsbereich
  129. faecher_nach_id 30
  130. end
  131. # wählt alle Fächergruppen aus.
  132. def faechergruppen
  133. [berufsuebergreifend, berufsbezogen, differenzierungsbereich]
  134. end
  135. # gibt den Namen des Klassenlehrers mit gekürztem Vornamen.
  136. def v_name_klassenlehrer
  137. v = klassenlehrer.Vorname
  138. n = klassenlehrer.Nachname
  139. "#{v[0]}. #{n}"
  140. end
  141. # gibt "Klassenlehrer" entsprechend Geschlecht zurück
  142. def klassenlehrer_in
  143. klassenlehrer.Geschlecht == "3" ? "Klassenlehrer" : "Klassenlehrerin"
  144. end
  145. # gibt das aktuelle Schuljahr als String im Format "2014/15" zurück.
  146. def schuljahr
  147. jahr = self.Jahr
  148. "#{jahr}/#{jahr-1999}"
  149. end
  150. end
  151. # Assoziation für Noten
  152. class Noten < Sequel::Model(:schuelerleistungsdaten)
  153. include SchildTypeSaver
  154. many_to_one :abschnitt, :class => :Abschnitt, :key => :Abschnitt_ID
  155. many_to_one :fach, :class => :Faecher, :key => :Fach_ID
  156. # Notenbezeichnung als String
  157. def note
  158. case self.NotenKrz
  159. when "1"
  160. "sehr gut"
  161. when "2"
  162. "gut"
  163. when "3"
  164. "befriedigend"
  165. when "4"
  166. "ausreichend"
  167. when "5"
  168. "mangelhaft"
  169. when "6"
  170. "ungenügend"
  171. when 'NB'
  172. "----------"
  173. when 'E3'
  174. "teilgenommen"
  175. end
  176. end
  177. # Bezeichnung des Fachs
  178. def bezeichnung
  179. fach.Bezeichnung
  180. end
  181. # Die Fachgruppen ID des Fachs
  182. def fachgruppe_ID
  183. fach.Fachgruppe_ID
  184. end
  185. end
  186. # Assoziation für Fächer
  187. class Faecher < Sequel::Model(:eigeneschule_faecher)
  188. include SchildTypeSaver
  189. one_to_one :noten
  190. end
  191. # Schul-Tabelle mit vereinfachtem Zugriff auf Datenfelder.
  192. class Schule < Sequel::Model(:eigeneschule)
  193. include SchildTypeSaver
  194. # gibt die Schulnummer zurück
  195. def self.schulnummer
  196. self.first.SchulNr
  197. end
  198. def self.v_name_schulleiter
  199. "#{self.first.SchulleiterVorname[0]}. #{self.first.SchulleiterName}"
  200. end
  201. def self.schulleiter_in
  202. self.first.SchulleiterGeschlecht == 3 ? "Schulleiter" : "Schulleiterin"
  203. end
  204. def self.ort
  205. self.first.Ort
  206. end
  207. end
  208. end