Browse Source

(re)Add angles to public.json

Jocelyn Delande 9 years ago
parent
commit
a157572b0d

+ 24 - 1
wifiwithme/apps/contribmap/models.py

@@ -5,6 +5,7 @@ from __future__ import unicode_literals
 from django.db import models
 
 from .fields import CommaSeparatedCharField
+from .utils import ANGLES, merge_intervals
 
 
 class Contrib(models.Model):
@@ -109,12 +110,29 @@ class Contrib(models.Model):
         'floor_total': 'privacy_place_details',
         'orientations': 'privacy_place_details',
         'roof': 'privacy_place_details',
+        'angles': 'privacy_place_details',
     }
+
     PUBLIC_FIELDS = set(PRIVACY_MAP.keys())
 
     def __str__(self):
         return '#{} {}'.format(self.pk, self.name)
 
+    def angles(self):
+        """Return a list of (start, stop) angles from cardinal orientations
+        """
+        # Cleanup
+        if self.orientations is None:
+            return []
+        orientations = [o for o in self.orientations if o in ANGLES.keys()]
+        # Hack to make leaflet-semicircle happy (drawing a full circle only
+        # works with (0, 360))
+        if len(orientations) == 8:
+            return [[0, 360]]
+        angles = [ANGLES[orientation] for orientation in self.orientations]
+        angles.sort(key=lambda i: i[0])  # sort by x
+        return merge_intervals(angles)
+
     def is_public(self):
         return not self.privacy_coordinates
 
@@ -131,6 +149,11 @@ class Contrib(models.Model):
         :return: the field value, or None, if the field is private
         """
         if self._may_be_public(field) and self._is_public(field):
-            return getattr(self, field)
+            v = getattr(self, field)
+            if hasattr(v, '__call__'):
+                return v()
+            else:
+                return v
+
         else:
             return None

+ 10 - 0
wifiwithme/apps/contribmap/tests.py

@@ -49,6 +49,16 @@ class TestContribPrivacy(TestCase):
         )
         self.assertEqual(c.get_public_field('name'), 'John')
 
+    def test_public_callable_field(self):
+        c = Contrib.objects.create(
+            name='John',
+            phone='010101010101',
+            orientations=['N'],
+            contrib_type=Contrib.CONTRIB_CONNECT,
+            privacy_name=True,
+        )
+        self.assertEqual(c.get_public_field('angles'), [[-23, 22]])
+
     def test_private_field(self):
         c = Contrib.objects.create(
             name='John',

+ 37 - 0
wifiwithme/apps/contribmap/utils.py

@@ -0,0 +1,37 @@
+ANGLES = {
+    'N': (-23, 22),
+    'NO': (292, 337),
+    'O': (247, 292),
+    'SO': (202, 247),
+    'S': (157, 202),
+    'SE': (112, 157),
+    'E': (67, 112),
+    'NE': (22, 67)
+}
+
+ORIENTATIONS = ANGLES.keys()
+
+
+def merge_intervals(l, wrap=360):
+    """Merge a list of intervals, assuming the space is cyclic.  The
+    intervals should already by sorted by start value."""
+    if l == []:
+        return []
+    result = list()
+    # Transform the 2-tuple into a 2-list to be able to modify it
+    result.append(list(l[0]))
+    for (start, stop) in l:
+        current = result[-1]
+        if start > current[1]:
+            result.append([start, stop])
+        else:
+            result[-1][1] = max(result[-1][1], stop)
+    if len(result) == 1:
+        return result
+    # Handle the cyclicity by merging the ends if necessary
+    last = result[-1]
+    first = result[0]
+    if first[0] <= last[1] - wrap:
+        result[-1][1] = max(result[-1][1], first[1] + wrap)
+        result.pop(0)
+    return result

+ 1 - 1
wifiwithme/apps/contribmap/views.py

@@ -33,7 +33,7 @@ def public_json(request):
                 "name": i.get_public_field('name'),
                 "place": {
                     "floor": i.get_public_field('floor'),
-                    # "angles" : TODO
+                    "angles": i.get_public_field('angles'),
                     "orientations": i.get_public_field('orientations'),
                     "roof": i.get_public_field('roof'),
                     "floor": i.get_public_field('floor'),