[chronojump-server] Creates sprintResult page with all functionalities



commit 375bc64483cbca28fdce6bae8a177d00bbd81da3
Author: Max Ros i Morejon <mros33 gmail com>
Date:   Tue Jun 18 16:17:22 2019 +0200

    Creates sprintResult page with all functionalities

 .../organizations/api/serializers.py               |   2 +-
 .../chronojump_networks/organizations/api/views.py |   6 +-
 .../chronojump_networks/organizations/models.py    |  35 +-
 .../chronojump_networks/results/api/serializers.py |  21 +-
 .../chronojump_networks/results/api/urls.py        |  22 +-
 .../chronojump_networks/results/api/views.py       |  81 +++-
 .../chronojump_networks/results/models.py          |  26 ++
 .../chronojump_networks/results/urls.py            |   6 +-
 .../chronojump_networks/tasks/models.py            |   1 +
 .../chronojump_networks/templates/layout.html      |  11 +-
 .../organizations/groups/group_players_list.html   |  11 +-
 .../players/add_edit_player_form.html              |   4 +-
 .../organizations/players/players_list.html        |  10 +-
 .../chronojump_networks/templates/pages/index.html |   4 +-
 .../templates/results/results_list.html            |   8 +-
 .../templates/results/sprints_list.html            | 490 +++++++++++++++++++++
 chronojumpserver-django/rfid-csharp/RFID.cs        |  10 +-
 17 files changed, 713 insertions(+), 35 deletions(-)
---
diff --git a/chronojumpserver-django/chronojump_networks/organizations/api/serializers.py 
b/chronojumpserver-django/chronojump_networks/organizations/api/serializers.py
index a999c26..7b10180 100644
--- a/chronojumpserver-django/chronojump_networks/organizations/api/serializers.py
+++ b/chronojumpserver-django/chronojump_networks/organizations/api/serializers.py
@@ -8,7 +8,7 @@ class PlayerSerializer(serializers.ModelSerializer):
     player_tasks = PlayerTaskSerializer(many=True)
     class Meta:
         model = Player
-        fields = [ 'id', 'name', 'number', 'height', 'weight', 'image', 'player_tasks', 'rfid']
+        fields = [ 'id', 'name', 'number', 'height', 'weight', 'imageName', 'player_tasks', 'rfid']
 
 
 class GymSerializer(serializers.ModelSerializer):
diff --git a/chronojumpserver-django/chronojump_networks/organizations/api/views.py 
b/chronojumpserver-django/chronojump_networks/organizations/api/views.py
index d977a0c..aa4c327 100644
--- a/chronojumpserver-django/chronojump_networks/organizations/api/views.py
+++ b/chronojumpserver-django/chronojump_networks/organizations/api/views.py
@@ -168,7 +168,7 @@ class PlayerListView(ListCreateAPIView):
             print(new_photo)
         o = Player.objects.create(
             name = str(data['name'][0]),
-            image = newimage,
+            imageName = newimage,
             number = int(data['number'][0]),
             height = float(data['height'][0]),
             weight = float(data['weight'][0]),
@@ -194,11 +194,11 @@ class PlayerListView(ListCreateAPIView):
             try:
                 photo = data['image'][0]
             except KeyError:
-                o.image = '../static/images/default_player.png'
+                o.imageName = '../static/images/default_player.png'
             else:
                 photo = data['image'][0]
                 new_photo = photo.name + '_' + str(int(time()))
-                o.image = 'players/' + new_photo
+                o.imageName = 'players/' + new_photo
                 full_path = os.path.join(settings.MEDIA_ROOT, 'players', new_photo)
                 path = default_storage.save(full_path, ContentFile(photo.read()))  
         o.save()
diff --git a/chronojumpserver-django/chronojump_networks/organizations/models.py 
b/chronojumpserver-django/chronojump_networks/organizations/models.py
index f7daec0..734e2ca 100644
--- a/chronojumpserver-django/chronojump_networks/organizations/models.py
+++ b/chronojumpserver-django/chronojump_networks/organizations/models.py
@@ -92,11 +92,42 @@ class User(AbstractUser):
         gym_list = [gm.id for gm in gym_organization]
         stations = Station.objects.filter(gym_id__in = gym_list)
         return stations
-
+    
     def exercises_by_coach(self):
         station_list = self.stations_by_coach()
         exercices = Exercise.objects.filter(station_id__in = station_list)
         return exercices
+    
+    def encoder_stations_by_coach(self):
+        group_list = [g.group.id for g in self.groups_by_coach.all()]
+        group_organizations = Organization.objects.filter(groups__in = group_list)
+        organization_list = [gp.id for gp in group_organizations]
+        gym_organization = Gym.objects.filter(organization_id__in = organization_list)
+        gym_list = [gm.id for gm in gym_organization]
+        stations = Station.objects.filter(gym_id__in = gym_list)
+        stations = stations.exclude(type__exact = 'S')
+        return stations
+    
+    def encoder_exercises_by_coach(self):
+        station_list = self.encoder_stations_by_coach()
+        exercices = Exercise.objects.filter(station_id__in = station_list)
+        return exercices
+    
+    #def sprint_stations_by_coach(self):
+        #group_list = [g.group.id for g in self.groups_by_coach.all()]
+        #group_organizations = Organization.objects.filter(groups__in = group_list)
+        #organization_list = [gp.id for gp in group_organizations]
+        #gym_organization = Gym.objects.filter(organization_id__in = organization_list)
+        #gym_list = [gm.id for gm in gym_organization]
+        #stations = Station.objects.filter(gym_id__in = gym_list)
+        #stations = stations.filter(type__exact = 'S')
+        #return stations
+    
+    #def sprint_exercises_by_coach(self):
+        #station_list = self.sprint_stations_by_coach()
+        #exercices = Exercise.objects.filter(station_id__in = station_list)
+        #return exercices
+
 
 
 class Organization(ChronojumpBaseModel):
@@ -219,7 +250,7 @@ class Player(ChronojumpBaseModel):
     height = models.FloatField(default=0)
     weight = models.FloatField(default=0)
     rfid = models.CharField(max_length=23, unique=True)
-    image = models.FileField(upload_to='players', null=True, blank=True, 
default='../static/images/player.png')
+    imageName = models.FileField(upload_to='players', null=True, blank=True, 
default='../static/images/player.png')
     is_available = models.BooleanField(default=True)
     number = models.IntegerField(null=True,blank=True)
 
diff --git a/chronojumpserver-django/chronojump_networks/results/api/serializers.py 
b/chronojumpserver-django/chronojump_networks/results/api/serializers.py
index 8cca765..a9b19c5 100644
--- a/chronojumpserver-django/chronojump_networks/results/api/serializers.py
+++ b/chronojumpserver-django/chronojump_networks/results/api/serializers.py
@@ -1,6 +1,6 @@
 from rest_framework import serializers
 
-from ..models import ResultEncoder
+from ..models import ResultEncoder, ResultSprint
 
 
 class ResultEncoderSerializer(serializers.ModelSerializer):
@@ -33,3 +33,22 @@ class ResultEncoderSerializer(serializers.ModelSerializer):
                    'pmeanByPower',
                    'pmaxByPower',
                    'comments']
+
+class ResultSprintSerializer(serializers.ModelSerializer):
+    person = serializers.StringRelatedField()
+        
+    class Meta:
+        model = ResultSprint
+        fields = [ 'id',
+                   'dt',
+                   'person',
+                   'distances',
+                   't1',
+                   't2',
+                   't3',
+                   't4',
+                   'k',
+                   'vmax',
+                   'amax',
+                   'fmax',
+                   'pmax']
diff --git a/chronojumpserver-django/chronojump_networks/results/api/urls.py 
b/chronojumpserver-django/chronojump_networks/results/api/urls.py
index 920035a..c1bfd97 100644
--- a/chronojumpserver-django/chronojump_networks/results/api/urls.py
+++ b/chronojumpserver-django/chronojump_networks/results/api/urls.py
@@ -8,18 +8,34 @@ from . import views
 urlpatterns = [
     url(
         # regex=r'^(?P<organization_id>\d+)/(?P<group_id>\d+)/players$',
-        regex=r'^list$',
+        regex=r'^encoder/list$',
         view=views.ResultEncoderList.as_view(),
         name='results_list'
     ),
     url(
-        regex=r'^(?P<result_id>\d+)$',
+        regex=r'^encoder/(?P<result_id>\d+)$',
         view=views.ResultEncoderRetrieveUpdateDestroyAPIView.as_view(),
         name='results'
     ),
     url(
-        regex=r'^delete$',
+        regex=r'^encoder/delete$',
         view=views.ResultEncoderDestroyAPIView.as_view(),
         name='results_delete'
+    ),
+    url(
+        # regex=r'^(?P<organization_id>\d+)/(?P<group_id>\d+)/players$',
+        regex=r'^sprint/list$',
+        view=views.ResultSprintList.as_view(),
+        name='sprints_list'
+    ),
+    url(
+        regex=r'^sprint/(?P<result_id>\d+)$',
+        view=views.ResultSprintRetrieveUpdateDestroyAPIView.as_view(),
+        name='sprints'
+    ),
+    url(
+        regex=r'^sprint/delete$',
+        view=views.ResultSprintDestroyAPIView.as_view(),
+        name='sprints_delete'
     )
 ]
diff --git a/chronojumpserver-django/chronojump_networks/results/api/views.py 
b/chronojumpserver-django/chronojump_networks/results/api/views.py
index 943278b..0e7a2bf 100644
--- a/chronojumpserver-django/chronojump_networks/results/api/views.py
+++ b/chronojumpserver-django/chronojump_networks/results/api/views.py
@@ -1,5 +1,5 @@
-from ..models import ResultEncoder
-from .serializers import ResultEncoderSerializer
+from ..models import ResultEncoder, ResultSprint
+from .serializers import ResultEncoderSerializer, ResultSprintSerializer
 
 from django.http import HttpResponse, JsonResponse
 from django.shortcuts import get_object_or_404
@@ -81,6 +81,7 @@ class ResultEncoderList(ListAPIView):
             d = datetime.now() - timedelta(timeInterval)
             print(d)
             queryset = ResultEncoder.objects.filter(person__in = player_list, dt__gte = d, station__in = 
station_list, exercise__in = exercise_list)
+            stations = stations.exclude(type__exact = 'S')
         else:
             # No filter by time
             queryset = ResultEncoder.objects.filter(person__in = player_list, station__in = station_list, 
exercise__in = exercise_list)
@@ -120,3 +121,79 @@ class ResultEncoderDestroyAPIView(DestroyAPIView):
             o.delete()
             print("Result %d removed" % (int(result_id), ))
         return JsonResponse({}, status=204, safe=False)
+    
+
+class ResultSprintList(ListAPIView):
+    permission_classes = (IsAuthenticated, )
+    serializer_class = ResultSprintSerializer
+
+    def get(self, request, *args, **kwargs):
+        data = dict(request.GET)
+        org_id = int(data['org_id'][0])
+        coach_id = int(data['coach_id'][0])
+        group_id = str(data['group_id'][0])
+        timeInterval = int(data['timeInterval'][0])
+        player_id = str(data['player_id'][0])
+        
+        #GROUP SELECT
+        if group_id.lower() == "all":
+            # Get all results from all the groups of the coach
+            coach = get_object_or_404(User, pk=coach_id)
+            group_list = [g.group.id for g in coach.groups_by_coach.all()]
+
+            players = GroupPlayer.objects.filter(group_id__in = group_list)
+            player_list = [p.player_id for p in players]
+        else:
+            players = GroupPlayer.objects.filter(group_id = int(group_id))
+            player_list = [p.player_id for p in players]
+            
+        #PLAYER SELECT
+        if player_id.lower() != "all":
+            players = Player.objects.filter(id = int(player_id))
+            player_list_aux = [p.id for p in players]
+            player_list = [value for value in player_list if value in player_list_aux]
+            
+        if timeInterval > 0 :
+            print(timeInterval)
+            d = datetime.now() - timedelta(timeInterval)
+            print(d)
+            queryset = ResultSprint.objects.filter(person__in = player_list, dt__gte = d)
+        else:
+            # No filter by time
+            queryset = ResultSprint.objects.filter(person__in = player_list)
+        # Serialize the results and return
+        serializer = ResultSprintSerializer(queryset, many=True)
+        return Response(serializer.data)
+
+
+class ResultSprintRetrieveUpdateDestroyAPIView(RetrieveUpdateDestroyAPIView):
+
+    permission_classes = (IsAuthenticated, )
+    serializer_class = ResultSprintSerializer
+    lookup_field = 'result_id'
+
+    def retrieve(self, request, *args, **kwars):
+        #print(self.kwargs['task_id'])
+        o = get_object_or_404(Task, id=self.kwargs['result_id'])
+        s = ResultSprintSerializer(o)
+        return Response(s.data)
+
+    def destroy(self, request, *args, **kwargs):
+        o = get_object_or_404(Task, id=self.kwargs['result_id'])
+        o.delete()
+        print("Result %d removed" % (result_id, ))
+        return JsonResponse({}, status=204, safe=False)
+
+class ResultSprintDestroyAPIView(DestroyAPIView):
+    """Remove players from group"""
+    permission_classes = (IsAuthenticated, )
+    serializer_class = ResultSprintSerializer
+
+    def destroy(self, request, *args, **kwargs):
+
+        results_ids = request.data
+        for result_id in results_ids:
+            o = ResultSprint.objects.get(id=int(result_id))
+            o.delete()
+            print("Result %d removed" % (int(result_id), ))
+        return JsonResponse({}, status=204, safe=False)
diff --git a/chronojumpserver-django/chronojump_networks/results/models.py 
b/chronojumpserver-django/chronojump_networks/results/models.py
index ee38709..6a82082 100644
--- a/chronojumpserver-django/chronojump_networks/results/models.py
+++ b/chronojumpserver-django/chronojump_networks/results/models.py
@@ -65,3 +65,29 @@ class ResultEncoder(models.Model):
     pmeanByPower = models.FloatField(default=0.0)
     pmaxByPower = models.FloatField(default=0.0)
     comments = models.CharField(max_length=30, blank=True, null=True)
+    
+
+class ResultSprint(models.Model):
+    
+    class Meta:
+        db_table = 'resultSprint'
+
+    dt = models.DateTimeField(null=True)
+
+    person = models.ForeignKey(Player,
+                                     on_delete=models.CASCADE,
+                                     related_name='players_sprints',
+                                     db_column='personId')
+
+
+    distances = models.CharField(max_length=50, default="5m")
+    k = models.FloatField(default=0.0)
+    vmax = models.FloatField(default=0.0)
+    amax = models.FloatField(default=0.0)
+    fmax = models.FloatField(default=0.0)
+    pmax = models.FloatField(default=0.0)
+    t1 = models.FloatField(default=0.0)
+    t2 = models.FloatField(default=0.0)
+    t3 = models.FloatField(default=0.0)
+    t4 = models.FloatField(default=0.0)
+    
diff --git a/chronojumpserver-django/chronojump_networks/results/urls.py 
b/chronojumpserver-django/chronojump_networks/results/urls.py
index 7bcf801..b6dffb4 100644
--- a/chronojumpserver-django/chronojump_networks/results/urls.py
+++ b/chronojumpserver-django/chronojump_networks/results/urls.py
@@ -10,7 +10,11 @@ from . import views
 app_name = 'results'
 urlpatterns = [
     url(
-        regex=r'^$',
+        regex=r'^encoder$',
         view=login_required(TemplateView.as_view(template_name='results/results_list.html')),
         name='list'),
+    url(
+        regex=r'^sprint$',
+        view=login_required(TemplateView.as_view(template_name='results/sprints_list.html')),
+        name='sprint'),
 ]
diff --git a/chronojumpserver-django/chronojump_networks/tasks/models.py 
b/chronojumpserver-django/chronojump_networks/tasks/models.py
index c3f580f..29b7a75 100644
--- a/chronojumpserver-django/chronojump_networks/tasks/models.py
+++ b/chronojumpserver-django/chronojump_networks/tasks/models.py
@@ -65,3 +65,4 @@ class Task(models.Model):
                                   default=LATERALITY_BOTH )
     comment = models.CharField(max_length=150, null=True, blank=True)
     done = models.BooleanField(default=False)
+    
diff --git a/chronojumpserver-django/chronojump_networks/templates/layout.html 
b/chronojumpserver-django/chronojump_networks/templates/layout.html
index 48cb58d..681aaf1 100644
--- a/chronojumpserver-django/chronojump_networks/templates/layout.html
+++ b/chronojumpserver-django/chronojump_networks/templates/layout.html
@@ -12,8 +12,15 @@
       <li class="nav-item active">
         <a class="nav-link" href="/">{% trans 'Home' %} <span class="sr-only">(current)</span></a>
       </li>
-      <li class="nav-item">
-        <a class="nav-link active" href="{% url 'results:list' %}">{% trans 'Results' %}</a>
+      <li class="nav-item dropdown active">
+        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownResults" data-toggle="dropdown" 
aria-haspopup="true" aria-expanded="false">
+          {% trans 'Results' %}
+        </a>
+        <div class="dropdown-menu" aria-labelledby="navbarDropdownResults">
+          <h6 class="dropdown-header">{% trans 'Results' %}</h6>
+          <a class="dropdown-item" href="{% url 'results:list' %}">{% trans 'Encoder results' %}</a>
+          <a class="dropdown-item" href="{% url 'results:sprint' %}">{% trans 'Sprint results' %}</a>
+        </div>
       </li>
       <!--<li class="nav-item">
         <a class="nav-link disabled" href="#">{% trans 'Sprints' %}</a>
diff --git 
a/chronojumpserver-django/chronojump_networks/templates/organizations/groups/group_players_list.html 
b/chronojumpserver-django/chronojump_networks/templates/organizations/groups/group_players_list.html
index fc2639f..ee08c8e 100644
--- a/chronojumpserver-django/chronojump_networks/templates/organizations/groups/group_players_list.html
+++ b/chronojumpserver-django/chronojump_networks/templates/organizations/groups/group_players_list.html
@@ -126,7 +126,7 @@
         {
                        type: "html",
                        title: "",
-                       data: 'image',
+                       data: 'imageName',
                        orderable: false,
                        render: function(value, type, row) {
             if (value) {
@@ -231,7 +231,12 @@
     /* Task child rows */
     function format ( d ) {
         // `d` is the original data object for the row
-               if (d.player_tasks.length > 0) {
+        //if (d.player_tasks;.length > 0) {
+            var found=0;
+            $.each(d.player_tasks, function(index, task) {
+                if(task.done==0) found=1;
+            })
+            if(found) {                
                        var html = '<table cellpadding="5" cellspacing="10" style="margin-left:50px;">';
                        html += "<thead><th></th><th>{% trans 'Gym' %}";
           html += "<th>{% trans 'Station' %}</th><th>{% trans 'Exercise' %}</th>";
@@ -239,6 +244,7 @@
           html += "<th>{% trans 'Load' %}</th></th><th>{% trans 'Speed' %}";
           html +="</th><th></th>"
                        $.each(d.player_tasks, function(index, task) {
+                       if(task.done==0) {
             console.log(task);
                                html += '<tbody><tr>';
                                html += '<td>' + (index + 1) + '</td>';
@@ -274,6 +280,7 @@
                                html += 'data-task-type="' + task.type + '">'
             html += '<i class="material-icons">delete_sweep</i></a>';
             html += '</td></tr>';
+                       }
                        });
                        html += "</tbody></table>";
 
diff --git 
a/chronojumpserver-django/chronojump_networks/templates/organizations/players/add_edit_player_form.html 
b/chronojumpserver-django/chronojump_networks/templates/organizations/players/add_edit_player_form.html
index 6dff114..8d8da6a 100644
--- a/chronojumpserver-django/chronojump_networks/templates/organizations/players/add_edit_player_form.html
+++ b/chronojumpserver-django/chronojump_networks/templates/organizations/players/add_edit_player_form.html
@@ -21,11 +21,11 @@
                             <img id="imgView" src="{% static 'images/default_player.png' %}" 
alt="player_image" style="width:100%;
                             height:100%; object-fit: contain">
                         </div>
-                        <div>
+                        <div class="form-group col-sm-8">
                                 <!--input id="clearImgId" type="button" name="clearImg" value="ClearImg"-->
                                 <button class="btn btn-outline-secondary" type="button" 
id="btn_delete_image">Delete Image</button>
                                                </div>
-                                               <div class="form-group col-sm-4">
+                                               <div class="form-group col-sm-8">
                                                        <p>
                                 <input id="id_image" type="file" class="" name="image" 
enctype='multipart/form-data'>
                             </p>
diff --git a/chronojumpserver-django/chronojump_networks/templates/organizations/players/players_list.html 
b/chronojumpserver-django/chronojump_networks/templates/organizations/players/players_list.html
index f23bfac..febbea5 100644
--- a/chronojumpserver-django/chronojump_networks/templates/organizations/players/players_list.html
+++ b/chronojumpserver-django/chronojump_networks/templates/organizations/players/players_list.html
@@ -80,7 +80,7 @@
         {
                        type: "html",
                        title: "",
-                       data: 'image',
+                       data: 'imageName',
                        orderable: false,
                        render: function(value, type, row) {
                     if (value) {
@@ -314,10 +314,10 @@
       $('#weight').val(player.weight);
       $('#number').val(player.number);
       $('#input_rfid').val(player.rfid);
-      console.log(player.image);      
-      $('#imgView').prop("src", player.image);
-      $('#id_image').val(player.image.name);
-      image_pl = player.image;
+      console.log(player.imageName);      
+      $('#imgView').prop("src", player.imageName);
+      $('#id_image').val(player.imageName.name);
+      image_pl = player.imageName;
     }
     
     function putPlayer(player) {
diff --git a/chronojumpserver-django/chronojump_networks/templates/pages/index.html 
b/chronojumpserver-django/chronojump_networks/templates/pages/index.html
index 9db1ea6..98f3ca1 100644
--- a/chronojumpserver-django/chronojump_networks/templates/pages/index.html
+++ b/chronojumpserver-django/chronojump_networks/templates/pages/index.html
@@ -60,10 +60,10 @@
     <h2 class="text-center">{% trans 'Player results' %}</h2>
     <div class="row buttons">
       <div class="col-sm-6">
-        <a class="btn btn-outline-dark btn-block font-weight-bold text-uppercase" href="{% url 
'results:list' %}">{% trans 'Results' %}</a>
+        <a class="btn btn-outline-dark btn-block font-weight-bold text-uppercase" href="{% url 
'results:list' %}">{% trans 'Encoder results' %}</a>
       </div>
       <div class="col-sm-6">
-        <a class="btn btn-outline-dark btn-block font-weight-bold text-uppercase" href="#">{% trans 
'Sprints' %}</a>
+        <a class="btn btn-outline-dark btn-block font-weight-bold text-uppercase" href="{% url 
'results:sprint' %}">{% trans 'Sprint results' %}</a>
       </div>
     </div>
     {% if user.groups_by_coach %}
diff --git a/chronojumpserver-django/chronojump_networks/templates/results/results_list.html 
b/chronojumpserver-django/chronojump_networks/templates/results/results_list.html
index 3df7482..0563eb9 100644
--- a/chronojumpserver-django/chronojump_networks/templates/results/results_list.html
+++ b/chronojumpserver-django/chronojump_networks/templates/results/results_list.html
@@ -22,7 +22,7 @@
     {% else %}
         <img src="{{STATIC_URL}}images/logo_club.png" class="img-fluid float-left" width="48px" 
height="48px" style="margin-top:12px;margin-right:10px;" />
     {% endif %}
-    <h1 class="display-4">{% trans 'Results' %}  <small class="text-muted" style="font-size:32px">{% trans 
'List' %}</small></h1>
+    <h1 class="display-4">{% trans 'Encoder results' %}  <small class="text-muted" style="font-size:32px">{% 
trans 'List' %}</small></h1>
   </div>
   <div class="col-sm-3">
 
@@ -63,7 +63,7 @@
     <label for="stationSelect">{% trans 'Filter by station' %}</label>
     <select name="station" class="form-control" id="stationSelect">
       <option value="all">{% trans 'All stations' %}
-      {% for station in user.stations_by_coach %}
+      {% for station in user.encoder_stations_by_coach %}
       <option value={{station.id}}>{{station.name}}</option>
       {% endfor %}
     </select>
@@ -72,7 +72,7 @@
     <label for="exerciseSelect">{% trans 'Filter by exercise' %}</label>
     <select name="exercise" class="form-control" id="exerciseSelect">
       <option value="all">{% trans 'All exercises' %}
-      {% for exercise in user.exercises_by_coach %}
+      {% for exercise in user.encoder_exercises_by_coach %}
       <option value={{exercise.id}}>{{exercise.name}}</option>
       {% endfor %}
     </select>
@@ -548,7 +548,7 @@
       $('.time-interval-btn').removeClass('active btn-primary').addClass('btn-secondary');
       $(this).removeClass('btn-secondary').addClass('btn-primary active');
       $('#time-interval').val(parseInt($(this).attr('data-time-interval')));
-      console.log("Chsange data interval to " + $('#time-interval').val());
+      console.log("Change data interval to " + $('#time-interval').val());
       table_results.ajax.reload(enableDeletion, true);
     })
 
diff --git a/chronojumpserver-django/chronojump_networks/templates/results/sprints_list.html 
b/chronojumpserver-django/chronojump_networks/templates/results/sprints_list.html
new file mode 100644
index 0000000..9265f97
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/results/sprints_list.html
@@ -0,0 +1,490 @@
+{% extends 'layout.html' %}
+{% load static i18n %}
+
+{% block title %}Chronojump Networks | {{user.organization.name}} | {% trans 'Sprints' %} {% endblock %}
+
+{% block css %}
+{{ block.super }}
+<link rel="stylesheet" href="https://cdn.datatables.net/1.10.16/css/dataTables.bootstrap4.min.css";>
+<link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.5.1/css/buttons.bootstrap4.min.css";>
+
+<!--<link rel="stylesheet" 
href="https://cdn.datatables.net/fixedcolumns/3.2.4/css/fixedColumns.bootstrap4.min.css";>-->
+
+{% endblock %}
+
+{% block content %}
+{% csrf_token %}
+
+<div class="page-header row">
+  <div class="col-sm-9">
+    {% if user.organization.image %}
+        <img src="{{MEDIA_URL}}{{ user.organization.image }}" class="img-fluid float-left" width="48px" 
height="48px" style="margin-top:12px;margin-right:10px;" />
+    {% else %}
+        <img src="{{STATIC_URL}}images/logo_club.png" class="img-fluid float-left" width="48px" 
height="48px" style="margin-top:12px;margin-right:10px;" />
+    {% endif %}
+    <h1 class="display-4">{% trans 'Sprint results' %}  <small class="text-muted" style="font-size:32px">{% 
trans 'List' %}</small></h1>
+  </div>
+  <div class="col-sm-3">
+
+  </div>
+</div>
+<div class="row datatables_wrapped">
+  <div class="col form-group">
+    <label>{% trans 'Filter by time' %}</label><br/>
+    <div class="btn-group" role="group" aria-label="Basic example">
+      <button type="button" class="btn btn-primary active time-interval-btn" data-time-interval="1">{% trans 
'1d' %}</button>
+      <button type="button" class="btn btn-secondary time-interval-btn" data-time-interval="2">{% trans '2d' 
%}</button>
+      <button type="button" class="btn btn-secondary time-interval-btn" data-time-interval="3">{% trans '3d' 
%}</button>
+      <button type="button" class="btn btn-secondary time-interval-btn" data-time-interval="7">{% trans '7d' 
%}</button>
+      <button type="button" class="btn btn-secondary time-interval-btn" data-time-interval="14">{% trans 
'14d' %}</button>
+      <button type="button" class="btn btn-secondary time-interval-btn" data-time-interval="-1">{% trans 
'All' %}</button>
+    </div>
+    <input type="hidden" id="time-interval" value="1" />
+  </div>
+  <div class="col form-group">
+    <label for="groupSelect">{% trans 'Filter by group' %}</label>
+    <select name="group" class="form-control" id="groupSelect">
+      <option value="all">{% trans 'All groups' %}
+      {% for group in user.groups_by_coach.all %}
+      <option value={{group.group.id}}>{{group.group.name}}</option>
+      {% endfor %}
+    </select>
+  </div>
+  <div class="col form-group">
+    <label for="playerSelect">{% trans 'Filter by player' %}</label>
+    <select name="player" class="form-control" id="playerSelect">
+      <option value="all">{% trans 'All players' %}
+      {% for player in user.players_by_coach %}
+      <option value={{player.id}}>{{player.name}}</option>
+      {% endfor %}
+    </select>
+  </div>
+  <!--<div class="col form-group">
+    <label for="stationSelect">{% trans 'Filter by station' %}</label>
+    <select name="station" class="form-control" id="stationSelect">
+      <option value="all">{% trans 'All stations' %}
+      {% for station in user.sprint_stations_by_coach %}
+      <option value={{station.id}}>{{station.name}}</option>
+      {% endfor %}
+    </select>
+  </div>
+  <div class="col form-group">
+    <label for="exerciseSelect">{% trans 'Filter by exercise' %}</label>
+    <select name="exercise" class="form-control" id="exerciseSelect">
+      <option value="all">{% trans 'All exercises' %}
+      {% for exercise in user.sprint_exercises_by_coach %}
+      <option value={{exercise.id}}>{{exercise.name}}</option>
+      {% endfor %}
+    </select>
+  </div>-->
+</div>
+<div class="row datatables_wrapped">
+  <div class="col">
+       <table id="sprints" cellspacing="0" cellpadding="0" class="table table-sm" style="width:100%">
+       </table>
+    <div id="hiddenContainer" style="display:none"/>
+  </div>
+</div>
+{% endblock content %}
+
+{% block javascript %}
+{{ block.super }}
+<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js";></script>
+<script src="https://cdn.datatables.net/1.10.16/js/dataTables.bootstrap4.min.js";></script>
+<script src="https://cdn.datatables.net/buttons/1.5.1/js/dataTables.buttons.min.js";></script>
+<script src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.bootstrap4.min.js";></script>
+<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js";></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.32/pdfmake.min.js";></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.32/vfs_fonts.js";></script>
+<script src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.print.min.js";></script>-->
+<script src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.html5.min.js";></script>
+
+
+<script>
+  var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
+  var refreshIntervalId;
+
+       var COLUMN_PLAYER = 4;
+//     var COLUMN_STATION = 5;
+//     var COLUMN_EXERCISE = 6;
+
+  function formatDateNumber(val) {
+       if (val < 10) {
+               return '0' + val;
+       } else {
+               return val;
+       }
+  }
+
+  $(document).ready(function() {
+    /* Datatable for players in groups */
+    var table_results = $('#sprints').DataTable({
+      lengthChange: false,
+      "ajax": {
+        "processing": true,
+        "url" : "{% url 'api_results:sprints_list' %}",
+        data: function(d){
+               d.group_id = $('#groupSelect').val();
+               d.player_id = $('#playerSelect').val();
+               d.org_id = "{{ user.organization.id }}"
+               d.coach_id = "{{ user.id }}"
+          d.timeInterval = $('#time-interval').val();
+       },
+        "dataSrc": ""
+      },
+      "order": [ 
+       [0, 'asc']
+      ],
+      "columns": [
+        {
+                       type: "num",
+                       title: "id",
+                       data: "id",
+                       visible: false
+               },
+        {
+                       type: "date",
+                       data: "dt",
+                       visible: false
+               },
+               {
+                       type: "html",
+                       orderable:false,
+                       render: function(value, type, row) {
+                               return '<input class="deleteCheckbox" type="checkbox" data-result-id="' + 
row.id + '"/>';
+                       }
+               },
+               {
+                       type: "customdate",
+                       title: "{% trans 'Date' %}",
+                       data: "dt",
+                       render: function(value) {
+
+                               // Compare with today
+                               today = new Date();
+                               // To adjust the hour
+                               var _offsetHours = today.getTimezoneOffset()/60;
+                               var dd = today.getDate();
+                               var mm = today.getMonth();
+                               var yy = today.getFullYear();
+
+                               var dt = new Date(value);
+                               dt.setHours(dt.getHours() + _offsetHours);
+                               var dd2 = dt.getDate();
+                               var mm2 = dt.getMonth();
+                               var yy2 = dt.getFullYear();
+                               var hh = dt.getHours();
+                               var MM = dt.getMinutes();
+                               if (dd == dd2 && mm == mm2 && yy == yy2) {
+                                       // Today, show the result hours and minute
+                                       return formatDateNumber(hh) + ':' + formatDateNumber(MM);
+                               } else if (yy == yy2) {
+                                       // Same year
+                                       return formatDateNumber(dd2) + "/" +formatDateNumber(mm2 + 1) + " " + 
formatDateNumber(hh) + ":" + formatDateNumber(MM);
+                               } else {
+                                       return formatDateNumber(dd2) + "/" + formatDateNumber(mm2 + 1) + "/" 
+ yy2 + " " + formatDateNumber(hh) + ":" + formatDateNumber(MM);
+                               }
+
+                       }
+               },
+        {
+                       type: "html",
+                       data: "person",
+                       title: "{% trans 'Player' %}"
+               },
+               {
+                       type: "html",
+                       data: "distances",
+                       title: "{% trans 'Distancia' %}"
+               },
+               {
+                       type: "num",
+                       data: "t1",
+                       title: "t1",
+                       className: 'colResult',
+                render: $.fn.dataTable.render.number('', ',', 2)
+               },
+               {
+                       type: "num",
+                       data: "t2",
+                       title: "t2",
+                       className: 'colResult',
+                render: $.fn.dataTable.render.number('', ',', 2)
+               },
+        {
+                       type: "num",
+                       data: "t3",
+                       title: "t3",
+                       className: 'colResult',
+                render: $.fn.dataTable.render.number('', ',', 2)
+               },
+               {
+                       type: "num",
+                       data: "t4",
+                       title: "t4",
+                       className: 'colResult',
+                render: $.fn.dataTable.render.number('', ',', 2)
+               },
+               {
+                       type: "num",
+                       data: "k",
+                       title: "k",
+                       className: 'colResult',
+                render: $.fn.dataTable.render.number('', ',', 2)
+               },
+               {
+                       type: "num",
+                       data: "vmax",
+                       title: "VMax",
+                       className: 'colResult',
+                render: $.fn.dataTable.render.number('', ',', 2)
+               },
+               {
+                       type: "num",
+                       data: "amax",
+                       title: "AMax",
+                       className: 'colResult',
+                render: $.fn.dataTable.render.number('', ',', 2)
+               },
+               {
+                       type: "num",
+                       data: "fmax",
+                       title: "FMax",
+                       className: 'colResult',
+                render: $.fn.dataTable.render.number('', ',', 2)
+               },
+               {
+                       type: "num",
+                       data: "pmax",
+                       title: "PMax",
+                       className: 'colResult',
+                render: $.fn.dataTable.render.number('', ',', 2)
+               }
+      ],
+      "dom": "<'row'<'col-sm-6'B><'col-sm-6'f>>rtip",
+      buttons: [
+        { text: "{% trans 'Export results' %}", className: "btn btn-primary",
+               action: function( e, dt, node, config ) {
+                       var columns = ["{% trans 'Date' %}", "{% trans 'Player' %}", "{% trans 'Distancia' 
%}", "t1", "t2", "t3", "t4", "k", "VMax", "AMax", "FMax", "FMax"];
+
+                       var csv = columns.join(";") + "\n";
+                       var today = new Date();
+                       var dd = today.getDate();
+                       var mm = today.getMonth()+1;
+                       var yyyy = today.getFullYear();
+                       var hh = today.getHours();
+                       var MM = today.getMinutes();
+
+                       var filename = "curses_" + yyyy + formatDateNumber(mm) + formatDateNumber(dd) + 
formatDateNumber(hh) + formatDateNumber(MM)   + ".csv";
+                       var rows = $("#sprints").dataTable().$('tr', {"filter":"applied"});
+                       rows.each(function( index ) {
+                               //console.log( index + ": " + table.row( this ).data() );
+                               var data = table_results.row(this).data();
+                               var date = new Date(data.dt);
+                               var _offsetHours = date.getTimezoneOffset()/60;
+                               // Show the date in dd/mm/yyyy
+                               var dateStr = formatDateNumber(date.getDate()) + "/" + 
formatDateNumber(date.getMonth() + 1 ) + "/" +
+                               date.getYear().toString().substr(-2);
+                               csv += dateStr + ";"
+                               + data.person + ";"
+                               + data.personName + ";"
+                    + data.distancia +";"
+                    + data.t1.toString().replace(".", ",") + ";"
+                    + data.t2.toString().replace(".", ",") + ";"
+                    + data.t3.toString().replace(".", ",") + ";"
+                    + data.t4.toString().replace(".", ",") + ";"
+                    + data.k.toString().replace(".", ",") + ";"
+                    + data.vmax.toString().replace(".", ",") + ";"
+                    + data.amax.toString().replace(".", ",") + ";"
+                    + data.fmax.toString().replace(".", ",") + ";"
+                    + data.pmax.toString().replace(".", ",") + "\n";
+                       });
+                       var csvData = 'data:text/csv;charset=utf-8,' + "\uFEFF" + encodeURI(csv);
+                       // For IE (tested 10+)
+                       //console.log(filename);
+                       //console.log(csv);
+                       if (window.navigator.msSaveOrOpenBlob) {
+                               var blob = new Blob([decodeURIComponent(encodeURI(csv))], {
+                                       type: "text/csv;charset=utf-8;"
+                               });
+                               navigator.msSaveBlob(blob, filename);
+                               alert();
+                       } else {
+                               var link=document.createElement('a');
+                               /*$(link)
+                               .attr({
+                               'download': filename
+                               ,'href': csvData
+                               //,'target' : '_blank' //if you want it to open in a new window
+                       });*/
+                       link.href= csvData;
+                       link.download=filename;
+                       document.getElementById('hiddenContainer').appendChild(link);
+                       link.click();
+               }
+               return csv;
+       }},
+       { text: "{% trans 'Delete race' %}",
+       className: "btn btn-danger btnDeleteResults",
+       enabled: false,
+       action: function(e, dt, node, config) {
+               // Ask for confirmation
+               var total =  $('.deleteCheckbox:checked').length;
+               if (total == 1) {
+
+                       var r = confirm("{% trans 'Are you sure to delete this race?' %}");
+               } else {
+                       var r = confirm("{% trans 'Are you sure to delete these races?' %}");
+               }
+               if (r == true) {
+                       var results = [];
+                       $.each($('.deleteCheckbox:checked'), function(index, value) {
+                               var v = $(value);
+                               console.log(index + ":" + v.attr('data-result-id'));
+                               results.push(v.attr('data-result-id'));
+
+                       });
+                       var url = "{% url 'api_results:sprints_delete' %}";
+          $.ajax({
+                               url: url,
+                               type: "DELETE",
+                               contentType: 'application/json;charset=UTF-8',
+                               data: JSON.stringify(results)
+                       }).done(function(msg){
+                               // Results have been deleted. Refresh table and enable again the interval
+                               //console.log(msg);
+                               $('.btnDeleteResults').addClass('disabled');
+                               table_results.ajax.reload(enableDeletion, false);
+                               refreshIntervalId = refreshIntervalTrigger();
+                               console.log("Interval refresh is enabled with id " + refreshIntervalId);
+                       })
+               }
+       }}
+      ],
+      initComplete: function() {
+        this.api().columns().every(function() {
+
+               var column = this;
+               var idx = column.index();
+               if (idx == COLUMN_PLAYER) {
+                       var select = $('<select class="form-control"><option value="">{% trans "All players" 
%}</option></select>')
+                       .appendTo($('#playerSelect'))
+                       .on('change', function() {
+                               // Player selected
+                               console.log("canvi player select");
+                               var val = $.fn.dataTable.util.escapeRegex(
+                                       $(this).val()
+                               );
+
+                               column
+                               .search(val ? '^' + val + '$' : '', true, false)
+                               .draw();
+                               // Hide column if is a selected Player
+                               //console.log(val);
+                               column.visible(val == '');
+
+                       });
+
+                       column.data().unique().sort().each(function(d, j) {
+                               select.append('<option value="' + d + '">' + d + '</option>')
+                       });
+            }
+       });
+       console.log("Enable delection for first time");
+        enableDeletion();
+      },
+      "language": {
+       "lengthMenu": "{% trans 'Showing _MENU_ results per page' %}",
+       "zeroRecords": "{% trans 'There are no results to show' %}",
+       "info": "{% trans 'Showing the results _START_ to _END_ of a total of _TOTAL_ results' %}",
+       "infoEmpty": "{% trans 'The query returns no results' %}",
+       "infoFiltered": "{% trans '_MAX_ results filtered' %}",
+       "decimal": ",",
+       "thousands": ".",
+       "paginate": {
+               "first": '<i class="fa fa-fast-backward"></i>',
+               "last": '<i class="fa fa-fast-forward"></i>',
+               "next": '<i class="fa fa-forward"></i>',
+               "previous": '<i class="fa fa-backward"></i>'
+       },
+       "search": "{% trans 'Search:' %}"
+      }
+    });
+
+    /* Enable the result deletion */
+    function enableDeletion() {
+       // Called every time a delete checkbox is changed
+       //alert();
+       console.log("enableDeletion called");
+       $('.deleteCheckbox').on('change', function() {
+               var totalChecked = $('.deleteCheckbox:checked').length;
+               console.log(totalChecked);
+               if (totalChecked > 0) {
+                       // Disable the refresh interval
+                       if (refreshIntervalId != -1) {
+                               console.log("Clear interval Id " + refreshIntervalId);
+                               clearInterval(refreshIntervalId);
+                               console.log("Interval refresh is disabled");
+                               refreshIntervalId = -1;
+                               $('.btnDeleteResults').removeClass('disabled');
+                       }
+                       console.log("refreshIntervalId = " + refreshIntervalId);
+               } else {
+                       // Enable again the refresh interval
+                       $('.btnDeleteResults').addClass('disabled');
+                       refreshIntervalId = refreshIntervalTrigger();
+                       console.log("Interval refresh is enabled with id " + refreshIntervalId);
+               }
+       });
+    }
+
+    $('#results').on( 'draw.dt', function () {
+       console.log( 'Table redrawn' );
+       deselectAllCheckboxes();
+    } );
+
+    function deselectAllCheckboxes() {
+       //$('.deleteCheckbox').attr("checked", false);
+       $('.deleteCheckbox').prop("checked", false);
+       $('.btnDeleteResults').addClass('disabled');
+       if (refreshIntervalId == -1) {
+               refreshIntervalId = refreshIntervalTrigger();
+               console.log("Interval refresh is enabled with id " + refreshIntervalId);
+       }
+    }
+
+    function refreshIntervalTrigger() {
+       return setInterval(function() {
+               /* Set the interval for refresh */
+               table_results.ajax.reload(enableDeletion, false);
+       }, 15000);
+    };
+
+    refreshIntervalId = refreshIntervalTrigger();
+    console.log("Interval refresh is enabled with id " + refreshIntervalId);
+
+    /* Reload results for the group selected */
+    $('#groupSelect').on('change', function() {
+       table_results.ajax.reload(enableDeletion, true);
+        console.log("Reload by group change");
+    });
+    
+    /* Reload results for the player selected */
+    $('#playerSelect').on('change', function() {
+       table_results.ajax.reload(enableDeletion, true);
+        console.log("Reload by player change");
+    });
+    
+
+    $('.time-interval-btn').on('click', function() {
+      $('.time-interval-btn').removeClass('active btn-primary').addClass('btn-secondary');
+      $(this).removeClass('btn-secondary').addClass('btn-primary active');
+      $('#time-interval').val(parseInt($(this).attr('data-time-interval')));
+      console.log("Change data interval to " + $('#time-interval').val());
+      table_results.ajax.reload(enableDeletion, true);
+    })
+
+  }); // End of document ready
+
+</script>
+{% endblock %}
diff --git a/chronojumpserver-django/rfid-csharp/RFID.cs b/chronojumpserver-django/rfid-csharp/RFID.cs
index 2560bf7..a1838b5 100755
--- a/chronojumpserver-django/rfid-csharp/RFID.cs
+++ b/chronojumpserver-django/rfid-csharp/RFID.cs
@@ -29,17 +29,17 @@ public class RFIDMain
        public static void Main()
        {
                //debug starts
-               /*string str = "Called RFIDMain. Writing at /tmp/rfidcalled.txt";
+               string str = "Called RFIDMain. Writing at /tmp/rfidcalled.txt";
                Console.WriteLine(str);
        
-               TextWriter writer = File.CreateText("/tmp/rfidcalled.txt");
+               /*TextWriter writer = File.CreateText("/tmp/rfidcalled.txt");
                writer.Write(str);
                writer.Flush();
                writer.Close();
                ((IDisposable)writer).Dispose();*/
                //debug ends
 
-               //removeFile();
+               removeFile();
 
                RFID rfid = new RFID();
                RFID.StatusEnum status = rfid.Start();
@@ -52,11 +52,11 @@ public class RFIDMain
                        Console.WriteLine(status.ToString());
        }
                
-       /*private static void removeFile()
+       private static void removeFile()
        {
                if(File.Exists(rfidFile))
                        File.Delete(rfidFile);
-       }*/
+       }
 
        private static void write(string str)
        {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]