No Description

views.py 8.9KB

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