aboutsummaryrefslogtreecommitdiff
path: root/sgdfi/_dbs/_code.py
blob: b416e3027d3f3dab58c97e784bf2deac410e3469 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#!/usr/bin/env python3
#******************************************************************************
# Copyright (C) 2018 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
# This file is part of the sgdfi project, which is MIT-licensed.
#******************************************************************************
""" Code decoding for SGDFi. """

from enum import Enum as _Enum, unique as _unique

from ._st import StructureType as _StructureType

__all__ = ["Code", "CodeType"]

@_unique
class CodeType(_Enum):
	""" Unknown code type. """
	UNKNOWN = 0

	""" Structure. """
	STRUCTURE = 1

	""" Adherent. """
	ADHERENT = 2

_strcodeallowed = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'

def _strcode(value):
	""" Normalize the code and validate it. """

	oldvalue = value

	try:
		value = f"{int(value):09d}"
	except ValueError:
		pass

	value = value.strip().upper()
	value = value.rjust(9, '0')

	if len(value) != 9 or any(c not in _strcodeallowed for c in value):
		raise ValueError(f"Can't get a code out of {repr(oldvalue)}")
	return value

class Code:
	""" A structure code, which is a 9-digit number. """

	def __init__(self, value):
		self.__code = _strcode(value)

		# Try to deduce things of this code.
		# This algorithm is an implementation of the one described in
		# the documentation, in `env/intranet/index.rst`.

		typ  = CodeType.UNKNOWN
		styp = None
		sec  = value[:2]
		dep  = None
		depn = None
		grpn = None

		if   value == '000000000':
			typ = CodeType.STRUCTURE
			styp = _StructureType.SOMMET
		elif value[2:] in ('0000000', '9999999'):
			typ = CodeType.STRUCTURE
			styp = _StructureType.CENTRE_NATIONAL
		elif value[:2] in ('12', '13', '14', '15', '16', '17'):
			typ = CodeType.ADHERENT
		elif value[:2] == '98':
			typ = CodeType.STRUCTURE

			if value[2:7] == '88001':
				if value[8] == '8':
					styp = _StructureType.ASSOCIES_N
				else:
					styp = _StructureType.CENTRE_NATIONAL
			else:
				if value[7] == '8':
					styp = _StructureType.ASSOCIES_N
				else:
					styp = _StructureType.CENTRE_NATIONAL
		else:
			dep = value[2:4]
			depn = int(value[4])

			typ = CodeType.STRUCTURE

			if value[5:7] == '00':
				if value[7:9] == '00':
					styp = _StructureType.TERRITOIRE
				else:
					styp = _StructureType.ASSOCIES_T
			else:
				grpn = int(value[5:7]) - 1

				if value[7:9] == '00':
					styp = _StructureType.GROUPE
				elif value[7] == '1':
					styp = _StructureType.UNITE_8_11_ANS
				elif value[7] == '2':
					styp = _StructureType.UNITE_11_14_ANS
				elif value[7] == '3':
					styp = _StructureType.UNITE_14_17_ANS
				elif value[7] == '7':
					styp = _StructureType.UNITE_FARFADET
				elif value[7] == '9':
					styp = _StructureType.UNITE_VENT_DU_LARGE
				else:
					styp = _StructureType.ASSOCIES_L

		self.__type    = typ
		self.__subtype = styp
		self.__sector  = sec
		self.__dep     = dep
		self.__depn    = depn
		self.__grpn    = grpn

	def __repr__(self):
		p = [f"code = {self.__code}"]
		if self.__type != CodeType.UNKNOWN:
			p.append(f"type = {self.__type}")
		if self.__type == CodeType.STRUCTURE:
			p.append(f"subtype = {self.__subtype}")
		if self.__sector is not None:
			p.append(f"sector = {self.__sector}")
		if self.__dep is not None:
			p.append(f"dep = {self.__dep}")
		if self.__depn is not None:
			p.append(f"depn = {self.__depn}")
		if self.__grpn is not None:
			p.append(f"grpn = {self.__grpn}")

		return f"{self.__class__.__name__}({', '.join(p)})"

	def __str__(self):
		return self.__code

	def __eq__(self, value):
		try:
			code = _strcode(value)
			return self.__code == code
		except ValueError:
			return False

	@property
	def type(self):
		""" The code type. """

		return self.__type

	@property
	def subtype(self):
		""" The code subtype. """

		return self.__subtype

	@property
	def sector(self):
		""" The sector (first two characters). """

		return self.__sector

	@property
	def department(self):
		""" The code of the associated administrative department. """

		return self.__dep

	@property
	def territory_index(self):
		""" The number of the territory in the administrative department. """

		return self.__depn

	@property
	def group_index(self):
		""" The index of the group in the territory. """

		return self.__grpn

# End of file.