1+ from apps .shared .models import BaseModel
2+ from django .contrib .gis .db import models
3+ from django .contrib .gis .geos import Point
4+ from django .core .cache import cache
5+ from django_prometheus .models import ExportModelOperationsMixin
6+ from apps .shared .enums import CacheKey
7+ import re
8+ from typing import Tuple
9+
10+ NTCIP_TOKEN_PATTERN = re .compile (r"\[[^\]]+\]" )
11+
12+ def parse_dms_pages (raw : str ) -> Tuple [str , str , str ]:
13+ if not raw :
14+ return "" , "" , ""
15+
16+ text = raw
17+
18+ # Normalize newlines
19+ text = re .sub (r"\[nl\]" , "\n " , text , flags = re .IGNORECASE )
20+
21+ # Split pages BEFORE removing other tokens
22+ pages = re .split (r"\[np\]" , text , flags = re .IGNORECASE )
23+
24+ cleaned_pages = []
25+
26+ for page in pages [:3 ]: # max 3 pages
27+ # Remove remaining NTCIP formatting tokens
28+ page = NTCIP_TOKEN_PATTERN .sub ("" , page )
29+
30+ # Normalize whitespace
31+ page = re .sub (r"[ \t]+" , " " , page )
32+ page = re .sub (r"\n{3,}" , "\n \n " , page )
33+
34+ cleaned_pages .append (page .strip ())
35+
36+ # Pad missing pages
37+ while len (cleaned_pages ) < 3 :
38+ cleaned_pages .append ("" )
39+
40+ return tuple (cleaned_pages )
41+
42+
43+ class Dms (ExportModelOperationsMixin ('dms' ), BaseModel ):
44+ id = models .CharField (primary_key = True , max_length = 128 , blank = True , default = '' )
45+ name = models .CharField (max_length = 128 , blank = True , default = '' )
46+ name_override = models .CharField (blank = True , max_length = 128 )
47+ category = models .CharField (max_length = 128 , blank = True , default = '' )
48+ description = models .CharField (max_length = 750 , blank = True , default = '' )
49+ roadway_name = models .CharField (max_length = 128 , blank = True , default = '' )
50+ roadway_direction = models .CharField (max_length = 64 , blank = True , default = '' )
51+ static_text = models .CharField (max_length = 256 , blank = True , default = '' )
52+ message_text = models .CharField (max_length = 512 , blank = True , default = '' )
53+ status = models .CharField (max_length = 64 , blank = True , default = '' )
54+ location = models .GeometryField (blank = True , null = True )
55+ updated_datetime_utc = models .DateTimeField (blank = True , null = True )
56+ message_expiry_datetime_utc = models .DateTimeField (blank = True , null = True )
57+ cache_datetime_utc = models .DateTimeField (blank = True , null = True )
58+
59+ message_display_1 = models .TextField (blank = True , default = "" )
60+ message_display_2 = models .TextField (blank = True , default = "" )
61+ message_display_3 = models .TextField (blank = True , default = "" )
62+
63+ is_on = models .BooleanField (default = True )
64+
65+ def __str__ (self ):
66+ return f"dms for { self .pk } "
67+
68+ def save (self , * args , ** kwargs ):
69+ self .message_display_1 , self .message_display_2 , self .message_display_3 = (
70+ parse_dms_pages (self .message_text )
71+ )
72+ super ().save (* args , ** kwargs )
73+ cache .delete (CacheKey .DMS_LIST )
0 commit comments