From bf4767d280cb31a73b62ebb6ff912c604423de52 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 1 Mar 2025 20:02:19 +0000 Subject: [PATCH] first commit --- __init__.py | 0 __pycache__/__init__.cpython-310.pyc | Bin 0 -> 132 bytes __pycache__/admin.cpython-310.pyc | Bin 0 -> 173 bytes __pycache__/apps.cpython-310.pyc | Bin 0 -> 440 bytes __pycache__/models.cpython-310.pyc | Bin 0 -> 170 bytes __pycache__/urls.cpython-310.pyc | Bin 0 -> 397 bytes __pycache__/views.cpython-310.pyc | Bin 0 -> 5114 bytes admin.py | 3 + apps.py | 6 + migrations/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 143 bytes models.py | 3 + .../city_digital_twin.html | 51 ++++ tests.py | 3 + urls.py | 10 + views.py | 243 ++++++++++++++++++ 16 files changed, 319 insertions(+) create mode 100644 __init__.py create mode 100644 __pycache__/__init__.cpython-310.pyc create mode 100644 __pycache__/admin.cpython-310.pyc create mode 100644 __pycache__/apps.cpython-310.pyc create mode 100644 __pycache__/models.cpython-310.pyc create mode 100644 __pycache__/urls.cpython-310.pyc create mode 100644 __pycache__/views.cpython-310.pyc create mode 100644 admin.py create mode 100644 apps.py create mode 100644 migrations/__init__.py create mode 100644 migrations/__pycache__/__init__.cpython-310.pyc create mode 100644 models.py create mode 100644 templates/pxy_city_digital_twins/city_digital_twin.html create mode 100644 tests.py create mode 100644 urls.py create mode 100644 views.py diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/__pycache__/__init__.cpython-310.pyc b/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7b81b5b3974e25ff5c97f576ca1bcd27cd34021d GIT binary patch literal 132 zcmd1j<>g`kg4c{Y(?RrO5P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;!Hzequp^enCZL zd~#+g`kf|rat)9r!uV-N=!FabFZKwK;UBvKes7;_kM8KW2(8B&;n88n$+0!0}# z8E>&BrsQVk`Drpm@ug%X=B4NBCFkdr6lEqAfecv5P{a(Rz{D>V{ltO-{ep_h_~guz s%J`Jb^vsgPocNOR%)DZKurYcCmA5!-a`RJ4b5iXXff|cJh6peK03p#QoB#j- literal 0 HcmV?d00001 diff --git a/__pycache__/apps.cpython-310.pyc b/__pycache__/apps.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d24ea9f00c43e9c3233e16b5fae52a0ca1e56c11 GIT binary patch literal 440 zcmZuty-ve05VqqKh5jt4LSjHdV#<=f075NAuvJJfWwA^zjf|Wh;zTs8@G=ZM0I%Ye z3GoI@+%=Wxz)5$$pYQu@Uojf>8QM4hNZ;}Nq+-{6ET-u81OqVOhGjhFoLw{UK)f;# z34al>2mUP!dtZoRA$R+;vYZ$BN~cTe>>9^nif+dk5*Bk{$mX#CFZMy8itmnY*6m!^ z?WIn2t<2q%&TS|6d<+jNPm2idqpX0$*yuv1v!*VtbYj3Amg`n7kt(6%%9_ZFu;&6P zbCo4hy1taiZ4Bi@DIXhUwvz)$R;n?zRH!Id8%dvLZ>*w4ZNks#M3v>_|C?xJqq408 u!fAVU4@1Cw9`H?X5ehfheuA)-N4kXmyP?Yl*mJ>I_tbORn^8;f6^L2qLK literal 0 HcmV?d00001 diff --git a/__pycache__/models.cpython-310.pyc b/__pycache__/models.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9e5d153b15b187d04d7202eba24b891341376571 GIT binary patch literal 170 zcmd1j<>g`kf>(??(=CDYV-N=!FabFZKwK;UBvKes7;_kM8KW2(8B&;n88n$+0!0}# z8E>)W=BK3Q6#Hp1-QrBiO3X{o*Gow%0%=~!P{abHz{D?A{ltO-{ep_h_~guz%J`Jb m^vsgPocNOR%)DZKh!J`PmA5!-fb7zoR69nX&SH=$0t^7OOD5p} literal 0 HcmV?d00001 diff --git a/__pycache__/urls.cpython-310.pyc b/__pycache__/urls.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7a146d5b480e8290fee1e22fd326e7326e5938af GIT binary patch literal 397 zcmZvYJ5Izf5QfKb60%Q;0%{Odnstw&6(^vfOF*$zwg4jhCdaFw)F%MqYq z98s(kM)Hh*>z~gaH>=egD8AT7@yGx^oj8q<#2qb@P(nafLd8y&SiHmdsf)=WxI}ujJwCAB3^`gm5t>kl{WKhXwBPx@b0?E{*o+WdmrR zN_swN85U%s39Qt$c?Ufs+nBy@MBcWdeeJVJlM#-*Y5O5css_7KZr%LG{rwV_Z0)ak G^z#dKOLCb2 literal 0 HcmV?d00001 diff --git a/__pycache__/views.cpython-310.pyc b/__pycache__/views.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d546196469a0f5617b7d89a9afaf31afe1bf44b4 GIT binary patch literal 5114 zcmbVQTXP&o6`t;yot?dCb+K&8a^fg)NZ2Bh*DG0;iE&KqgaB1af^&f_!e+ERT8+Is zv+n7QE!Aulg$!|CLh(dF=^^F`{Q;`-58wyD!#qLpw8dkfOqoi;cY0RRN{&L2nVQq* zobEm|eQtev!jX}@f$Jaaw_SiM%MF&5NQKL0b?dF^aY*#>6<<5iunu z#c|9m3G=#9p6=t#MwutJ^aA0@WW4FAdboPSYoL+!#mZutCD~V$>HuA7WN7%{%A$4f zT*VXp0buh=%mlm1WlkAeMlTaAf##r}k9p^KY}{ZUabXJUKJW3^?3^BOGMZz?R_ECP z$JQK6nK9pDJ&x8yYofK#TFQtqAGnEkSjvhSxS6+&pkNs)v+;dq(5;}EE%q~Z+lVvK z>nclMB%Cbi@#AeqFU&;I=>?v2l~*77C@m{7zw^=?i3tlOrXQ$eglx6HC+v<8R zNf}CM;e(Sg>i6!r?M}eI0-^N8b~Cf=w{TB&x(6 zZvC_fjDK#KHgkB9$>SK@AdBo?gwx8jBhCVWgBV-d6{F$+CpRql#&v`hOm40u?A+$l z=c)_d;`yZubKdgB)wy$3u`uU?o?EOgEuC9DcVV$oslffsNXasjB}mq5O~E9Q6yIe$ z5iMidw3uaTUIXNTYXp@3zPmsK!h!+;PX;#}RXE!@LBVT@0-hp;Z^~_Qj7AXSMhJ_E zZ5!i`A&4hIA17LmIH4s?iD`^JDQ3heE$=Z%D z=>_yJuP&ZHw*aJCU0$tLcXCIHuZ>7o_}!?!8Y&ecISfb@c4`H^z`By%;AX9u5-rbt z&x;c0njd*?_1ETf(BV}_adB(MAnMt z0hFPT=VRkOvhoK;%6zhlG4cJwG7uCcuH9rT8c1UBwgK0B9OLY`>`TP{ZD|Z``|G-$&6qsW*@QG6ee5?xnbH6)}%2_I5;A+&F?dY@E2^^=oz<)H0FY_ zD>ZUr${+TMBv03ymz*K&6anpWTsuHwqcTBt3lF5l)^fW_jF85|+x3?%UQ+aOl&|W<|)K*4^?dJKwFs^qnAtZI5%zd^2n?XYGsa^ zIEVU}PoW-;^IL4n=oKKtrT`wuD1s^uWQ?SEJOUXd%qVU#NEjJNu;UWRgp5(h$i_$n z0~uqW#s)IRQ#>Arj0wyhquG!(PH$IsJTZ`QEIqNPY+Oh~rZgoAM;yCaJ95 zoOqKCRb0A*xX7dLX2dY>YoJ@!Y0k=ypk>)@y4VDcLPC>Pe&mKGK-09jmGuC6Z1 z$7#sXm5S6#d71=JNhF^EK&^q~N++DeZmfrX1KS|cI7IB2@(K+j?@vrb#-R|Vm-hfId|l-<%_n;N6b`!bZsWu)U=tNJZvT^9-2rAlpeI1 ztbv(OL2KiXNwV4`&bB=;NG{C|&q3;DX(bHi*7gd_AuG(GTblxwJ4-l)EmU5qP}wOf z#CnH-OW@cZAaiLA{RK!w6g1@64|g?GWY$Cb^G6n2!a%*)cY%CGpEN0s^s-GlDBR}) zr*7@bd98xNo=+BceR2VBlgj|L?Av}zQ4ustEbWNe{iwPg6v!XH&;)_&ue*qGMVr_t>tw6>=LJW{iVEtwdcz(hkl` zmvHzEDOZo&la}&I)a*->-y~fRncU5UP6Xw7={6xxY% jsU3=L%e#zS+lZ*@7{mJMKSiE9XPlh#icg`kg4c{Y(?RrO5P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;!HKequp^enCZL zd~#+Vo7E`kQpDJnU`4-AFo$Xd5gm)H$SB`C)EyQ LRxuNhU||3NY!@KE literal 0 HcmV?d00001 diff --git a/models.py b/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/templates/pxy_city_digital_twins/city_digital_twin.html b/templates/pxy_city_digital_twins/city_digital_twin.html new file mode 100644 index 0000000..7ef66b1 --- /dev/null +++ b/templates/pxy_city_digital_twins/city_digital_twin.html @@ -0,0 +1,51 @@ + + + + + LDS City + + + + + + + + + + {% load static %} + + + + + + + {% for building in city_data.buildings %} + + + + + {% endfor %} + + + {% for lamp in city_data.lamps %} + + + + + + {% endfor %} + + + {% for tree in city_data.trees %} + + + + + + {% endfor %} + + + + + + diff --git a/tests.py b/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/urls.py b/urls.py new file mode 100644 index 0000000..a594400 --- /dev/null +++ b/urls.py @@ -0,0 +1,10 @@ +from django.urls import path +from . import views + +urlpatterns = [ + # Pattern to accept UUIDs + path('city/digital/twin//', views.city_digital_twin, name='city_digital_twin_uuid'), + + # Pattern to accept string words + path('city/digital/twin//', views.city_digital_twin, name='city_digital_twin_str'), +] diff --git a/views.py b/views.py new file mode 100644 index 0000000..925fbc7 --- /dev/null +++ b/views.py @@ -0,0 +1,243 @@ +from django.shortcuts import render, get_object_or_404 +from django.http import Http404 +import random +import math + +def city_digital_twin(request, city_id, innovation_pct=None, technology_pct=None, science_pct=None): + try: + if city_id == "random_city": + city_data = generate_random_city_data() + elif city_id == "dream": + # Retrieve percentages from GET parameters if not in URL + innovation_pct = innovation_pct or request.GET.get('innovation', 0) + technology_pct = technology_pct or request.GET.get('technology', 0) + science_pct = science_pct or request.GET.get('science', 0) + + # Convert to integers + innovation_pct = int(innovation_pct) + technology_pct = int(technology_pct) + science_pct = int(science_pct) + + city_data = generate_random_city_data(innovation_pct, technology_pct, science_pct) + else: + city_data = get_city_data(city_id) + except ValueError: + raise Http404("City data not found.") + + if not city_data: + city_data = get_example_data() + + context = {'city_data': city_data} + return render(request, 'pxy_city_digital_twins/city_digital_twin.html', context) + + + if not city_data: + # Fallback to example data if no city data is found + city_data = get_example_data() + + context = {'city_data': city_data} + return render(request, 'pxy_city_digital_twins/city_digital_twin.html', context) + +def get_city_data(city_id): + # Implement fetching logic here + # This is a mock function to demonstrate fetching logic + if str(city_id) == "1" or str(city_id) == "123e4567-e89b-12d3-a456-426614174000": + return { + # Real data retrieval logic goes here + } + return None + +def get_example_data(): + return { + 'buildings': [ + { + 'id': 1, + 'status': 'Occupied', + 'position_x': 0, + 'height': 10, + 'position_z': 0, + 'width': 5, + 'depth': 5, + 'color': '#8a2be2', + 'file': '', # No file for a simple box representation + }, + { + 'id': 2, + 'status': 'Vacant', + 'position_x': 10, + 'height': 15, + 'position_z': 10, + 'width': 7, + 'depth': 7, + 'color': '#5f9ea0', + 'file': '', # No file for a simple box representation + } + ], + 'lamps': [ + { + 'id': 1, + 'status': 'Functional', + 'position_x': 3, + 'position_z': 3, + 'height': 4, + 'color': '#ffff00', + }, + { + 'id': 2, + 'status': 'Broken', + 'position_x': 8, + 'position_z': 8, + 'height': 4, + 'color': '#ff0000', + } + ], + 'trees': [ + { + 'id': 1, + 'status': 'Healthy', + 'position_x': 5, + 'position_z': 5, + 'height': 6, + 'radius_bottom': 0.2, + 'radius_top': 1, + 'color_trunk': '#8b4513', + 'color_leaves': '#228b22', + }, + { + 'id': 2, + 'status': 'Diseased', + 'position_x': 15, + 'position_z': 15, + 'height': 6, + 'radius_bottom': 0.2, + 'radius_top': 1, + 'color_trunk': '#a0522d', + 'color_leaves': '#6b8e23', + } + ] + } + + + +def rectangular_layout(num_elements, max_dimension): + grid_size = int(math.sqrt(num_elements)) + spacing = max_dimension // grid_size + return [ + { + 'position_x': (i % grid_size) * spacing, + 'position_z': (i // grid_size) * spacing + } + for i in range(num_elements) + ] + +def circular_layout(num_elements, radius): + return [ + { + 'position_x': radius * math.cos(2 * math.pi * i / num_elements), + 'position_z': radius * math.sin(2 * math.pi * i / num_elements) + } + for i in range(num_elements) + ] + +def diagonal_layout(num_elements, max_position): + return [ + { + 'position_x': i * max_position // num_elements, + 'position_z': i * max_position // num_elements + } + for i in range(num_elements) + ] + +def triangular_layout(num_elements): + positions = [] + row_length = 1 + while num_elements > 0: + for i in range(row_length): + if num_elements <= 0: + break + positions.append({ + 'position_x': i * 10 - (row_length - 1) * 5, # Spread out each row symmetrically + 'position_z': row_length * 10 + }) + num_elements -= 1 + row_length += 1 + return positions + + + +def generate_random_city_data(innovation_pct=100, technology_pct=100, science_pct=100, max_position=100, radius=50): + num_buildings = random.randint(5, 35) + num_lamps = random.randint(5, 100) + num_trees = random.randint(5, 55) + + # Buildings layout distribution + num_rectangular_buildings = int(num_buildings * innovation_pct / 100) + num_circular_buildings = (num_buildings - num_rectangular_buildings) // 2 + num_triangular_buildings = num_buildings - num_rectangular_buildings - num_circular_buildings + + building_positions = rectangular_layout(num_rectangular_buildings, max_position) + \ + circular_layout(num_circular_buildings, radius) + \ + triangular_layout(num_triangular_buildings) + + # Lamps layout distribution + num_triangular_lamps = int(num_lamps * technology_pct / 100) + num_circular_lamps = (num_lamps - num_triangular_lamps) // 2 + num_diagonal_lamps = num_lamps - num_triangular_lamps - num_circular_lamps + + lamp_positions = triangular_layout(num_triangular_lamps) + \ + circular_layout(num_circular_lamps, radius) + \ + diagonal_layout(num_diagonal_lamps, max_position) + + # Trees layout distribution + num_circular_trees = int(num_trees * science_pct / 100) + num_triangular_trees = (num_trees - num_circular_trees) // 2 + num_diagonal_trees = num_trees - num_circular_trees - num_triangular_trees + + tree_positions = circular_layout(num_circular_trees, radius) + \ + triangular_layout(num_triangular_trees) + \ + diagonal_layout(num_diagonal_trees, max_position) + + buildings = [ + { + 'id': i + 1, + 'status': random.choice(['Occupied', 'Vacant', 'Under Construction']), + 'position_x': pos['position_x'], + 'position_z': pos['position_z'], + 'height': random.randint(10, 50), + 'width': random.randint(5, 20), + 'depth': random.randint(5, 20), + 'color': random.choice(['#8a2be2', '#5f9ea0', '#ff6347', '#4682b4']), + 'file': '' + } for i, pos in enumerate(building_positions) + ] + + lamps = [ + { + 'id': i + 1, + 'status': random.choice(['Functional', 'Non-functional']), + 'position_x': pos['position_x'], + 'position_z': pos['position_z'], + 'height': random.randint(3, 10), + 'color': random.choice(['#ffff00', '#ff0000', '#00ff00']), + } for i, pos in enumerate(lamp_positions) + ] + + trees = [ + { + 'id': i + 1, + 'status': random.choice(['Healthy', 'Diseased', 'Wilting']), + 'position_x': pos['position_x'], + 'position_z': pos['position_z'], + 'height': random.randint(5, 30), + 'radius_bottom': random.uniform(0.1, 0.5), + 'radius_top': random.uniform(0.5, 2.0), + 'color_trunk': '#8b4513', + 'color_leaves': random.choice(['#228b22', '#90ee90', '#8b4513']), + } for i, pos in enumerate(tree_positions) + ] + + return { + 'buildings': buildings, + 'lamps': lamps, + 'trees': trees, + }