Geen omschrijving

views.py 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. from django.shortcuts import render
  2. from counter.models import Counter, Reset
  3. from babel.dates import format_timedelta, format_datetime
  4. from datetime import datetime, timedelta
  5. from django import forms
  6. from django.http import HttpResponseRedirect
  7. from django.core import serializers
  8. from django.core.mail import EmailMessage
  9. from graphos.renderers import gchart
  10. from graphos.sources.simple import SimpleDataSource
  11. from graphos.sources.model import ModelDataSource
  12. import random
  13. import math
  14. import copy
  15. from django.utils import timezone
  16. class resetCounterForm(forms.ModelForm):
  17. class Meta:
  18. model = Reset
  19. fields = ['reason', 'counter']
  20. def home(request):
  21. # JSS above this limit will not be displayed on the col graph
  22. JSS_limit = 7
  23. maxJSS = 0
  24. bestSeumeursNumber = 15
  25. # Display counters
  26. counters = Counter.objects.all()
  27. lastResets = []
  28. # Calculates infos for each counter
  29. timezero = timedelta(0)
  30. for counter in counters:
  31. lastReset = Reset.objects.filter(
  32. counter=counter).order_by('-timestamp')
  33. if (lastReset.count() == 0):
  34. # This person never had the seum
  35. counter.lastReset = Reset()
  36. counter.lastReset.delta = timezero
  37. counter.lastReset.noSeum = True
  38. counter.CSSclass = "warning"
  39. else:
  40. counter.lastReset = lastReset[0]
  41. counter.lastReset.noSeum = False
  42. counter.lastReset.delta = datetime.now(
  43. ) - counter.lastReset.timestamp.replace(tzinfo=None)
  44. if ((counter.lastReset.delta.total_seconds()) / (24 * 3600) <
  45. JSS_limit):
  46. # Less than 7 JSS -> display on graph
  47. lastResets.append(
  48. [counter.trigramme,
  49. {'v': (counter.lastReset.delta.total_seconds()) /
  50. (24 * 3600),
  51. 'f': str(round(
  52. (counter.lastReset.delta.total_seconds()) /
  53. (24 * 3600), 1))}])
  54. # Updating the max JSS displayed on the graph to compute scale
  55. if (counter.lastReset.delta.total_seconds() / (24 * 3600) >
  56. maxJSS):
  57. maxJSS = (counter.lastReset.delta.total_seconds() /
  58. (24 * 3600))
  59. # Defining CSS attributes for the counter
  60. counter.CSSclass = "primary"
  61. counter.opacity = 0.3 + 0.7 * \
  62. math.exp(-(counter.lastReset.delta.total_seconds()) /
  63. (7 * 24 * 3600))
  64. # Computing the total number of resets for this counter
  65. counter.seumCount = Reset.objects.filter(
  66. counter=counter).count()
  67. counter.lastReset.formatted_delta = format_timedelta(
  68. counter.lastReset.delta, locale='fr', threshold=1)
  69. counter.isHidden = "hidden"
  70. counters = sorted(counters, key=lambda t: t.lastReset.delta)
  71. # Column graph
  72. if (len(lastResets) == 0):
  73. noGraph = True
  74. col_chart = None
  75. else:
  76. noGraph = False
  77. lastResets.sort(key=lambda x: x[1]['v'])
  78. lastResets.insert(0, ['Trigramme', 'Jours sans seum'])
  79. col_data = SimpleDataSource(lastResets)
  80. col_chart = gchart.ColumnChart(col_data, options={
  81. 'title': '',
  82. 'legend': 'none',
  83. 'vAxis': {
  84. 'viewWindow': {
  85. 'max': max(maxJSS, 1),
  86. 'min': 0
  87. },
  88. 'ticks': [1, 2, 3, 4, 5, 6, 7],
  89. 'title': 'Jours sans seum'
  90. },
  91. 'hAxis': {'title': 'Trigramme'},
  92. })
  93. # Timeline graph
  94. # Data pre-processing
  95. resets = Reset.objects.filter(
  96. timestamp__gte=timezone.now() - timedelta(days=1))
  97. if (resets.count() == 0):
  98. noTimeline = True
  99. line_chart = None
  100. else:
  101. noTimeline = False
  102. for reset in resets:
  103. reset.timestamp = {
  104. 'v': reset.timestamp.timestamp(),
  105. 'f': "Il y a " + format_timedelta(datetime.now() -
  106. reset.timestamp.replace(
  107. tzinfo=None),
  108. locale='fr', threshold=1)
  109. }
  110. reset.Seum = {
  111. 'v': 0, 'f': reset.counter.trigramme + " : " + reset.reason}
  112. # Drawing the graph
  113. line_data = ModelDataSource(resets, fields=['timestamp', 'Seum'])
  114. line_chart = gchart.LineChart(line_data, options={
  115. 'lineWidth': 0,
  116. 'pointSize': 10,
  117. 'title': '',
  118. 'vAxis': {'ticks': []},
  119. 'hAxis': {
  120. 'ticks': [
  121. {'v': (datetime.now() - timedelta(days=1)
  122. ).timestamp(), 'f': 'Il y a 24 h'},
  123. {'v': datetime.now().timestamp(), 'f': 'Présent'}
  124. ]
  125. },
  126. 'legend': 'none',
  127. 'height': 90
  128. })
  129. # Graph of greatest seumers
  130. seumCounts = []
  131. for counter in counters:
  132. seumCounts.append([counter.trigramme, Reset.objects.filter(
  133. counter=counter).count()])
  134. if (len(seumCounts) == 0):
  135. noBestSeum = True
  136. best_chart = None
  137. else:
  138. seumCounts.sort(key=lambda x: -x[1])
  139. noBestSeum = False
  140. seumCounts.insert(0, ['Trigramme', 'Nombre de seums'])
  141. best_data = SimpleDataSource(seumCounts[:bestSeumeursNumber])
  142. best_chart = gchart.ColumnChart(best_data, options={
  143. 'title': '',
  144. 'legend': 'none',
  145. 'vAxis': {'title': 'Nombre de seums'},
  146. 'hAxis': {'title': 'Trigramme'},
  147. })
  148. return render(request, 'homeTemplate.html', {
  149. 'counters': counters,
  150. 'col_chart': col_chart,
  151. 'line_chart': line_chart,
  152. 'best_chart': best_chart,
  153. 'noTimeline': noTimeline,
  154. 'noGraph': noGraph,
  155. 'noBestSeum': noBestSeum
  156. })
  157. def resetCounter(request):
  158. # Update Form counter
  159. if (request.method == 'POST'):
  160. # create a form instance and populate it with data from the request:
  161. data = dict(request.POST)
  162. counter = Counter.objects.get(pk=int(data['counter'][0]))
  163. reset = Reset()
  164. reset.counter = counter
  165. reset.reason = data['reason'][0]
  166. reset.timestamp = datetime.now()
  167. reset.save()
  168. # We send the emails only to those who have an email address
  169. emails = [u[0] for u in Counter.objects.all().values_list('email')
  170. if u[0] != 'null@localhost']
  171. # Now send emails to everyone
  172. email_to_send = EmailMessage(counter.name + ' a le seum',
  173. data['reason'][0] + '''
  174. --
  175. SeumBook™ - http://seum.merigoux.ovh
  176. P.S. : Pour ne plus recevoir ces messages, envoie un mail à denis.merigoux@gmail.com''',
  177. 'SeumMan <seum@merigoux.ovh>', emails, [],
  178. reply_to=emails)
  179. email_to_send.send()
  180. return HttpResponseRedirect(data['redirect'][0])
  181. def counter(request, id_counter):
  182. counter = Counter.objects.get(pk=id_counter)
  183. resets = Reset.objects.filter(counter=counter).order_by('-timestamp')
  184. firstReset = copy.copy(resets[len(resets) - 1])
  185. timezero = timedelta(0)
  186. # Display
  187. if (resets.count() == 0):
  188. counter.lastReset = Reset()
  189. counter.lastReset.delta = timezero
  190. counter.lastReset.noSeum = True
  191. seumFrequency = 'inconnu'
  192. else:
  193. counter.lastReset = resets[0]
  194. counter.lastReset.noSeum = False
  195. counter.lastReset.delta = datetime.now(
  196. ) - counter.lastReset.timestamp.replace(tzinfo=None)
  197. counter.lastReset.formatted_delta = format_timedelta(
  198. counter.lastReset.delta, locale='fr', threshold=1)
  199. counter.seumCount = Reset.objects.filter(
  200. counter=counter).count()
  201. seumFrequency = format_timedelta((
  202. datetime.now() - firstReset.timestamp.replace(tzinfo=None)) /
  203. counter.seumCount, locale='fr', threshold=1)
  204. for reset in resets:
  205. reset.date = format_datetime(
  206. reset.timestamp, locale='fr',
  207. format="EEEE dd MMMM Y 'à' HH:mm:ss").capitalize()
  208. # Timeline graph
  209. # Data pre-processing
  210. resets_graph = resets
  211. for reset in resets_graph:
  212. reset.timestamp = {
  213. 'v': reset.timestamp.timestamp(),
  214. 'f': "Il y a " + format_timedelta(
  215. datetime.now() - reset.timestamp.replace(tzinfo=None),
  216. locale='fr', threshold=1)
  217. }
  218. reset.Seum = {'v': 0, 'f': reset.reason}
  219. # Drawing the graph
  220. data = ModelDataSource(resets, fields=['timestamp', 'Seum'])
  221. chart = gchart.LineChart(data, options={
  222. 'lineWidth': 0,
  223. 'pointSize': 10,
  224. 'title': '',
  225. 'vAxis': {'ticks': []},
  226. 'hAxis': {'ticks': [{
  227. 'v': firstReset.timestamp.timestamp(),
  228. 'f': 'Il y a ' + format_timedelta(
  229. datetime.now() - firstReset.timestamp.replace(tzinfo=None),
  230. locale='fr', threshold=1)
  231. }, {
  232. 'v': datetime.now().timestamp(),
  233. 'f': 'Présent'}
  234. ]},
  235. 'legend': 'none',
  236. 'height': 90
  237. })
  238. return render(request, 'counterTemplate.html', {
  239. 'counter': counter,
  240. 'chart': chart,
  241. 'resets': resets,
  242. 'seumFrequency': seumFrequency
  243. })