civil-tools-v 0.0.2__py3-none-any.whl → 0.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,33 @@ from typing import List
2
2
  import matplotlib.pyplot as plt
3
3
  from matplotlib.axes import Axes
4
4
  import io
5
+ import numpy as np
6
+
7
+ plt.rcParams["font.sans-serif"] = ["SimHei"] # 用来正常显示中文标签
8
+ plt.rcParams["axes.unicode_minus"] = False
9
+ plt.rcParams["font.size"] = 14
10
+
11
+
12
+ def GetTicks(n_max=1):
13
+ if n_max == 0:
14
+ n_max = 100
15
+ m = int(np.log10(n_max))
16
+ if m <= 0 and n_max <= 1:
17
+ m -= 1
18
+ p = n_max / (10**m)
19
+ if p <= 2.2:
20
+ result = [i * 1 * 10**m for i in range(3)]
21
+ elif p <= 3.5:
22
+ result = [i * 2 * 10**m for i in range(3)]
23
+ elif p <= 5:
24
+ result = [i * 2.5 * 10**m for i in range(3)]
25
+ elif p <= 6.9:
26
+ result = [i * 3 * 10**m for i in range(4)]
27
+ elif p <= 8:
28
+ result = [i * 2 * 10**m for i in range(5)]
29
+ else:
30
+ result = [i * 2 * 10**m for i in range(6)]
31
+ return result
5
32
 
6
33
 
7
34
  class BasicPltPlotter:
@@ -11,6 +38,9 @@ class BasicPltPlotter:
11
38
  self.axes = [_axes]
12
39
  else:
13
40
  self.axes = _axes
41
+ self.fig.patch.set_facecolor("none")
42
+ for ax in self.axes:
43
+ ax.patch.set_facecolor("none")
14
44
  self.axes: List[Axes]
15
45
  self.__remove_border()
16
46
 
@@ -22,7 +52,7 @@ class BasicPltPlotter:
22
52
  def save_to_stream(self):
23
53
  # 将图片保存到内存中的 BytesIO 对象
24
54
  img_buffer = io.BytesIO()
25
- self.fig.savefig(img_buffer, format="png", dpi=300) # 保存为 PNG 格式
55
+ self.fig.savefig(img_buffer, format="png", dpi=150) # 保存为 PNG 格式
26
56
  plt.close() # 关闭图形,释放内存
27
57
  # 将指针重置到流的开头,以便后续读取
28
58
  img_buffer.seek(0)
@@ -38,21 +68,50 @@ class SeismicPlotter(BasicPltPlotter):
38
68
  else:
39
69
  fig_size = (6, 5)
40
70
  super().__init__(fig_num, fig_size)
71
+ self.kwargs_x = {
72
+ "label": "X",
73
+ "ls": "-",
74
+ "color": "k",
75
+ "marker": "o",
76
+ "ms": 3,
77
+ }
78
+ self.kwargs_y = {
79
+ "label": "X",
80
+ "ls": "-",
81
+ "color": "r",
82
+ "marker": "o",
83
+ "ms": 3,
84
+ }
41
85
  self.floor_num = floor_num
42
- self.__y_values = [i + 1 for i in range(self.floor_num)]
43
- self.__ax1_x = [i for i in range(self.floor_num)]
44
- self.__ax1_y = [i * 0.5 for i in range(self.floor_num)]
45
- self.__ax2_x = [i for i in range(self.floor_num)]
46
- self.__ax2_y = [i * 0.5 for i in range(self.floor_num)]
86
+ self.y_label = "层号"
87
+ self._y_values = [i + 1 for i in range(self.floor_num)]
88
+ self._y_major_ticks = self.__create_y_ticks()
89
+ self._y_minor_ticks = [i + 1 for i in range(self.floor_num)]
90
+ self._ax1_x = [i for i in range(self.floor_num)]
91
+ self._ax1_y = [i * 0.5 for i in range(self.floor_num)]
92
+ self._ax2_x = [i for i in range(self.floor_num)]
93
+ self._ax2_y = [i * 0.5 for i in range(self.floor_num)]
47
94
 
48
95
  def test_plot(self):
49
96
  self.__plot()
50
97
 
51
98
  def __plot(self):
52
- kwargs_x = {"label": "X", "ls": "-", "color": "k", "marker": "o", "ms": 3}
53
- kwargs_y = {"label": "X", "ls": "-", "color": "r", "marker": "o", "ms": 3}
99
+ self.axes[0].plot(self._ax1_x, self._y_values, **self.kwargs_x)
100
+ self.axes[0].plot(self._ax1_y, self._y_values, **self.kwargs_y)
101
+ self.axes[1].plot(self._ax2_x, self._y_values, **self.kwargs_x)
102
+ self.axes[1].plot(self._ax2_y, self._y_values, **self.kwargs_y)
103
+
104
+ def __create_y_ticks(self):
105
+ floor_num = self.floor_num
106
+ return range(0, int(floor_num) + 1, int(floor_num // 5) + 1)
54
107
 
55
- self.axes[0].plot(self.__ax1_x, self.__y_values, **kwargs_x)
56
- self.axes[0].plot(self.__ax1_y, self.__y_values, **kwargs_y)
57
- self.axes[1].plot(self.__ax2_x, self.__y_values, **kwargs_x)
58
- self.axes[1].plot(self.__ax2_y, self.__y_values, **kwargs_y)
108
+ def _validate_list_length(self, data_list, name):
109
+ """
110
+ 验证列表长度是否与楼层数相等
111
+ :param data_list: 待验证的列表
112
+ :param name: 列表的名称,用于异常信息
113
+ """
114
+ if len(data_list) != self.floor_num:
115
+ raise ValueError(
116
+ f"Length of {name} is not equal to floor number: {self.floor_num}!"
117
+ )
@@ -0,0 +1,73 @@
1
+ from ..BasicPltPlotter import SeismicPlotter, GetTicks
2
+ from typing import List
3
+ import numpy as np
4
+ import matplotlib.pyplot as plt
5
+
6
+
7
+ class ShearMassRatioPlotter(SeismicPlotter):
8
+ def __init__(self, fig_num=2, floor_num=8):
9
+ super().__init__(fig_num, floor_num)
10
+ self.__limit = None
11
+ self.type = "剪重比"
12
+
13
+ def set_data(self, shear_x: List[float], shear_y: List[float], mass: List[float]):
14
+ if len(shear_x) != self.floor_num:
15
+ raise ValueError(
16
+ f"Lenght of shear_x is not equal to floor number: {self.floor_num}!"
17
+ )
18
+ if len(shear_y) != self.floor_num:
19
+ raise ValueError(
20
+ f"Lenght of shear_y is not equal to floor number: {self.floor_num}!"
21
+ )
22
+ if len(mass) != self.floor_num:
23
+ raise ValueError(
24
+ f"Lenght of mass is not equal to floor number: {self.floor_num}!"
25
+ )
26
+
27
+ self._ax1_x = np.array(shear_x) / np.array(mass)
28
+ self._ax2_x = np.array(shear_y) / np.array(mass)
29
+
30
+ def set_limit(self, limit: float):
31
+ self.__limit = limit
32
+
33
+ def plot(self):
34
+ if self.__limit:
35
+ self.__plot_limit()
36
+ kwargs_x = self.kwargs_x.copy()
37
+ kwargs_x["label"] = "X"
38
+ kwargs_y = self.kwargs_x.copy()
39
+ kwargs_y["label"] = "Y"
40
+ self.axes[0].plot(self._ax1_x, self._y_values, **kwargs_x)
41
+ self.axes[1].plot(self._ax2_x, self._y_values, **kwargs_y)
42
+ self.__adjust_lim()
43
+ self.__add_titles()
44
+
45
+ def __plot_limit(self):
46
+ limitation = self.__limit
47
+ for ax in self.axes:
48
+ ax.vlines(
49
+ x=limitation,
50
+ ymin=0,
51
+ ymax=self.floor_num,
52
+ color="r",
53
+ linewidth=3,
54
+ ls="--",
55
+ label=f"限值{limitation*100:.1f}%",
56
+ )
57
+
58
+ def __adjust_lim(self):
59
+ xmaxs = [self._ax1_x.max(), self._ax2_x.max()]
60
+ for i in range(2):
61
+ self.axes[i].set_xlim(left=0, right=xmaxs[i] * 1.2)
62
+ self.axes[i].set_yticks(self._y_major_ticks)
63
+ self.axes[i].set_yticks(self._y_minor_ticks, minor=True)
64
+ x_ticks = GetTicks(xmaxs[i])
65
+ self.axes[i].set_xticks(x_ticks)
66
+ self.axes[i].set_xticklabels([f"{i*100:.1f}%" for i in x_ticks])
67
+
68
+ def __add_titles(self):
69
+ self.axes[0].set_ylabel(self.y_label)
70
+ self.axes[0].set_xlabel(f"X小震下{self.type}")
71
+ self.axes[1].set_xlabel(f"Y小震下{self.type}")
72
+ self.axes[0].legend(framealpha=0, fontsize=12, loc=4)
73
+ self.axes[1].legend(framealpha=0, fontsize=12, loc=4)
@@ -0,0 +1,71 @@
1
+ from ..BasicPltPlotter import SeismicPlotter, GetTicks
2
+ from typing import List
3
+ import numpy as np
4
+ import matplotlib.pyplot as plt
5
+
6
+
7
+ class ShearMomentPlotter(SeismicPlotter):
8
+ def __init__(self, floor_num=8, type="Shear", fig_num=2):
9
+ super().__init__(fig_num, floor_num)
10
+ self.__limit = None
11
+ if type.lower() == "shear":
12
+ self.type = "楼层剪力 kN"
13
+ elif type.lower() == "moment":
14
+ self.type = "倾覆力矩 MN·m"
15
+ else:
16
+ raise ValueError("Only shear or moment is supported for type.")
17
+
18
+ def set_data(
19
+ self,
20
+ wind_x: List[float],
21
+ wind_y: List[float],
22
+ seismic_x: List[float],
23
+ seismic_y: List[float],
24
+ ):
25
+ # 验证数据长度
26
+ data_dict = {
27
+ "wind_x": wind_x,
28
+ "wind_y": wind_y,
29
+ "seismic_x": seismic_x,
30
+ "seismic_y": seismic_y,
31
+ }
32
+ for name, data_list in data_dict.items():
33
+ self._validate_list_length(data_list, name)
34
+
35
+ self._ax1_x = np.array(wind_x)
36
+ self._ax1_y = np.array(wind_y)
37
+ self._ax2_x = np.array(seismic_x)
38
+ self._ax2_y = np.array(seismic_y)
39
+
40
+ def plot(self):
41
+ if self.__limit:
42
+ self.__plot_limit()
43
+ kwargs_x = self.kwargs_x.copy()
44
+ kwargs_x["label"] = "X风"
45
+ kwargs_y = self.kwargs_y.copy()
46
+ kwargs_y["label"] = "Y风"
47
+ self.axes[0].plot(self._ax1_x, self._y_values, **kwargs_x)
48
+ self.axes[0].plot(self._ax1_y, self._y_values, **kwargs_y)
49
+ kwargs_x["label"] = "X小震"
50
+ kwargs_y["label"] = "Y小震"
51
+ self.axes[1].plot(self._ax2_x, self._y_values, **kwargs_x)
52
+ self.axes[1].plot(self._ax2_y, self._y_values, **kwargs_y)
53
+ self.__adjust_lim()
54
+ self.__add_titles()
55
+
56
+ def __adjust_lim(self):
57
+ xmaxs = [self._ax1_x.max(), self._ax2_x.max()]
58
+ for i in range(2):
59
+ self.axes[i].set_xlim(left=0, right=xmaxs[i] * 1.2)
60
+ self.axes[i].set_yticks(self._y_major_ticks)
61
+ self.axes[i].set_yticks(self._y_minor_ticks, minor=True)
62
+ x_ticks = GetTicks(xmaxs[i])
63
+ self.axes[i].set_xticks(x_ticks)
64
+ # self.axes[i].set_xticklabels([f"{i*100:.1f}%" for i in x_ticks])
65
+
66
+ def __add_titles(self):
67
+ self.axes[0].set_ylabel(self.y_label)
68
+ self.axes[0].set_xlabel(f"风下{self.type}")
69
+ self.axes[1].set_xlabel(f"小震下{self.type}")
70
+ self.axes[0].legend(framealpha=0, fontsize=12, loc=1)
71
+ self.axes[1].legend(framealpha=0, fontsize=12, loc=1)
@@ -0,0 +1,2 @@
1
+ from .ShearMassRatio import ShearMassRatioPlotter
2
+ from .ShearMoment import ShearMomentPlotter
@@ -12,17 +12,25 @@ class SingleMassResult:
12
12
  ):
13
13
  self.floor_num = floor_num
14
14
  self.tower_num = tower_num
15
- self.dead_load = dead_load
15
+ self.dead_load = round(dead_load, 4)
16
16
  """单层恒载,单位kN,没有折减"""
17
- self.live_load = live_load
17
+ self.live_load = round(live_load, 4) * 2
18
18
  """单层活载,单位kN,没有折减"""
19
- self.slab_area = slab_area
19
+ self.slab_area = round(slab_area)
20
20
  """单层楼板面积,单位m2"""
21
21
 
22
22
  @property
23
23
  def total_load(self):
24
24
  """单层质量,恒+0.5活"""
25
- return self.dead_load + 0.5 * self.live_load
25
+ return round(self.dead_load + 0.5 * self.live_load, 4)
26
+
27
+ def to_json(self):
28
+ return {
29
+ "floor_num": self.floor_num,
30
+ "tower_num": self.tower_num,
31
+ "dead_load": self.dead_load,
32
+ "live_load": self.live_load,
33
+ }
26
34
 
27
35
 
28
36
  class MassResult:
@@ -52,3 +60,6 @@ class MassResult:
52
60
  mass_list.append(SingleMassResult(i + 1, 1, 5000, 2000, 350))
53
61
 
54
62
  return MassResult(mass_list)
63
+
64
+ def to_json(self):
65
+ return {"mass_list": [i.to_json() for i in self.mass_list]}
@@ -64,6 +64,9 @@ class SinglePeriod:
64
64
  def __repr__(self):
65
65
  return str(self)
66
66
 
67
+ def to_json(self):
68
+ return {"index": self.index, "time": self.time}
69
+
67
70
 
68
71
  class Period:
69
72
  def __init__(self, periods: List[SinglePeriod], model_type=None):
@@ -144,6 +147,9 @@ class Period:
144
147
  )
145
148
  return Period(single_period_list)
146
149
 
150
+ def to_json(self):
151
+ return {"periods": [i.to_json() for i in self.periods]}
152
+
147
153
 
148
154
  class ValuePeer:
149
155
  def __init__(self, x: float, y: float):
@@ -158,6 +164,9 @@ class ValuePeer:
158
164
  else:
159
165
  return f"X:{self.x:.3f}\tY:{self.y:.3f}"
160
166
 
167
+ def to_json(self):
168
+ return {"X": self.x, "Y": self.y}
169
+
161
170
 
162
171
  class FloorSeismicResult:
163
172
  def __init__(
@@ -186,6 +195,13 @@ class FloorSeismicResult:
186
195
  def __repr__(self):
187
196
  return self.__str__()
188
197
 
198
+ def to_json(self):
199
+ return {
200
+ "floor_num": self.floor_num,
201
+ "tower_num": self.tower_num,
202
+ "shear": self.shear.to_json(),
203
+ }
204
+
189
205
 
190
206
  class SeismicResult:
191
207
  def __init__(self, floor_result: List[FloorSeismicResult]):
@@ -214,6 +230,9 @@ class SeismicResult:
214
230
  def __repr__(self):
215
231
  return self.__str__()
216
232
 
233
+ def to_json(self):
234
+ return {"floor_result": [i.to_json() for i in self.floor_result]}
235
+
217
236
 
218
237
  if __name__ == "__main__":
219
238
  p_list = []
@@ -153,8 +153,8 @@ class YDBLoader:
153
153
  row_data = self.connector.extract_table_by_columns(table_name, useful_columns)
154
154
  mass_list = []
155
155
  for temp_mass in row_data:
156
- floor_num = RowDataFactory.convert_to_int(temp_mass, 0)
157
- tower_num = RowDataFactory.convert_to_int(temp_mass, 1)
156
+ floor_num = RowDataFactory.convert_to_int(temp_mass[0])
157
+ tower_num = RowDataFactory.convert_to_int(temp_mass[1])
158
158
  mass_info = RowDataFactory.extract_list(temp_mass, 2)
159
159
  dead_load = RowDataFactory.convert_to_float(mass_info[1])
160
160
  live_load = RowDataFactory.convert_to_float(mass_info[2])
@@ -225,7 +225,6 @@ class YDBLoader:
225
225
  force = ValuePeer(force_x, force_y)
226
226
  shear = ValuePeer(shear_x, shear_y)
227
227
  moment = ValuePeer(moment_x, moment_y)
228
-
229
228
  temp_floor_result = FloorSeismicResult(
230
229
  floor_num, tower_num, force, shear, moment
231
230
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: civil_tools_v
3
- Version: 0.0.2
3
+ Version: 0.0.3
4
4
  Summary: A powerful tool for civil engineer in their work.
5
5
  Home-page: https://github.com/VincentXGao/civil-tools
6
6
  Author: Xinyu Gao (Vincent)
@@ -9,9 +9,12 @@ CivilTools/DXFGenerator/DrawingAttribs.py,sha256=F3CElw80JVKxh9zYMAeQDKJSsmq-GRq
9
9
  CivilTools/DXFGenerator/LayerManager.py,sha256=_FelBJNUsnDn66ZdVqBdnfYHvQ7roAO6irgFf2mDkjQ,664
10
10
  CivilTools/DXFGenerator/__init__.py,sha256=0jtyx5QnPbhauFfgjj4I5uqCwTy-nSuKtT-tbyEUiwQ,147
11
11
  CivilTools/FigureGenerator/BasicPNGPlotter.py,sha256=7PjRuArFc4y-NYy6WQCyfkpCahVCwtipJYEKk1My1D4,1982
12
- CivilTools/FigureGenerator/BasicPltPlotter.py,sha256=4Fup44jHQfzlfsLX4PQWcitcp-nEOFeyNLxLqR79oa0,2210
12
+ CivilTools/FigureGenerator/BasicPltPlotter.py,sha256=DNuBgg5qwi0kbttrNLcnAr1G1rYNunNCOaLwc5_8dzk,4002
13
13
  CivilTools/FigureGenerator/StairCalculationSheetPNGPlotter.py,sha256=iVOEY3MXu7x9D1d3W6fofPCUOHaR06lT9CsssNGqeBI,200
14
14
  CivilTools/FigureGenerator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ CivilTools/FigureGenerator/SeismicReport/ShearMassRatio.py,sha256=XpmPA9PeRED4Xzl_5LgJVgm9jEHuTda2GAFs5zMfVP8,2731
16
+ CivilTools/FigureGenerator/SeismicReport/ShearMoment.py,sha256=dYa4SK20u6MJXDsLAkpGk8t2U2tu3bEmBheu5D5nHek,2660
17
+ CivilTools/FigureGenerator/SeismicReport/__init__.py,sha256=W4yE7-BWQ1aiG-_oR7A08L6TtpIA-dlebtuGpU2-uOM,96
15
18
  CivilTools/ReportGenerator/BasicGenerator.py,sha256=h5FDZvk0X0BozZrLFWxdvcUd2JjERIVUauTscdpi8zw,11329
16
19
  CivilTools/ReportGenerator/DocParagraph.py,sha256=xJ9VWbi3IFu5nwJAS56ooQ49bCk4EBvme6IaY46DRP4,428
17
20
  CivilTools/ReportGenerator/DocPicture.py,sha256=9bJ6Zjw7Z6yB_h_H1_2wL9KZxA14zW-jmsKb_EEGxAc,246
@@ -21,7 +24,7 @@ CivilTools/ReportGenerator/SeismicReportTemplate.py,sha256=TxgRBCT0vW25AMYvuAtrV
21
24
  CivilTools/ReportGenerator/StairCalculationReport.py,sha256=gr2fafvYjTJCM4_JIiE9G5xbiy4W30TfmEjj3DW882Q,21566
22
25
  CivilTools/ReportGenerator/UtilFunctions.py,sha256=7qvAsZvoJN9pakENjBMYhrqP73xj5T4FuhSHa1t8lSA,9398
23
26
  CivilTools/ReportGenerator/__init__.py,sha256=1FVcNtNFstmE8zEFABs9oVw7rHiulvUKx0tD1GNFJ58,332
24
- CivilTools/YDBLoader/YDBLoader.py,sha256=zwd7TBbo4UR2JsP60XON7gGkhCASjoaRlGoxqBGqBPc,11111
27
+ CivilTools/YDBLoader/YDBLoader.py,sha256=2lwJn1oEU_aHWPbOu6pGZbJqpZLdEoTFqSjeZ4jE7fM,11109
25
28
  CivilTools/YDBLoader/YDBType.py,sha256=KVk_qpOwp4yAsHn96L5PAVTMMO8SU4lFOnnTMsH_qP0,109
26
29
  CivilTools/YDBLoader/__init__.py,sha256=dOomroeul9yiQQ3FZQVhnfYav43sDv1hUltoA0BrmLw,144
27
30
  CivilTools/YDBLoader/BuildingDefine/ComponentType.py,sha256=soUKmSeeY6dCO4IMrLuaF3GcOj8HgzeCQOtudTSqhno,146
@@ -34,8 +37,8 @@ CivilTools/YDBLoader/BuildingDefine/Geometry/Grid.py,sha256=BVhmbu8DndZYprVATKp7
34
37
  CivilTools/YDBLoader/BuildingDefine/Geometry/Joint.py,sha256=MjJ2CkNOgnQYCbmOeauiwW63ooHwHZlGzib1v2nPnE0,725
35
38
  CivilTools/YDBLoader/BuildingDefine/Geometry/StandFloor.py,sha256=lxh5l_H9dl4udvt0zjsWVkF1JLgURC5dfisfEenHnrY,29
36
39
  CivilTools/YDBLoader/BuildingDefine/Geometry/__init__.py,sha256=8eX2KQlOvtqnJqZ8QTc8HTCEuTv6xk1JeIeFdBoGpYQ,86
37
- CivilTools/YDBLoader/BuildingDefine/GlobalResult/BasicResult.py,sha256=11ZxUPfHXOUsH1J4qfYApQKx3tkrK5_DoQpqnyYdbBY,1458
38
- CivilTools/YDBLoader/BuildingDefine/GlobalResult/SeismicResult.py,sha256=pEPeTrzzZQX7Um5wmlN9Szwb5XqRy_DBeI7Azc-DCt0,6298
40
+ CivilTools/YDBLoader/BuildingDefine/GlobalResult/BasicResult.py,sha256=5M6Y0k1pvrsC9HskmPkMvEbsIESbRkjMNUttU1Y5JBc,1817
41
+ CivilTools/YDBLoader/BuildingDefine/GlobalResult/SeismicResult.py,sha256=KoaQmF57_C2-EjVxYr1uu8ZVy_F_Ih-7yeYckkDvhYo,6825
39
42
  CivilTools/YDBLoader/BuildingDefine/GlobalResult/__init__.py,sha256=cquJ_qevVkhpHRKKNJl8g_3WlmOhvejV4HthYhO0ZZI,150
40
43
  CivilTools/YDBLoader/BuildingDefine/Section/Section.py,sha256=wFWHKbrf1VUeCM2fVbrCDERGvcaTqE6gmLiV2RO7cNs,1644
41
44
  CivilTools/YDBLoader/BuildingDefine/Section/ShapeEnum.py,sha256=hTHx2wnNp1hMhRDM5upxxhgTpYGFF23rolfPpUcJFiI,856
@@ -50,8 +53,8 @@ CivilTools/YDBLoader/SQLiteConnector/Connector.py,sha256=TWr8SNdYrL3WqMVC3NqLfk6
50
53
  CivilTools/YDBLoader/SQLiteConnector/RowDataFactory.py,sha256=CRStFrV9ac2bi_R1CB6LW4_MrXhMtfyOFWgrT31PkI4,1537
51
54
  CivilTools/YDBLoader/SQLiteConnector/YDBTableName.py,sha256=X71ka_a4CU39_r6_jtW2BO9nQe_wiequ4ELE77rvfVA,2614
52
55
  CivilTools/YDBLoader/SQLiteConnector/__init__.py,sha256=0WWCCdLvlX0Rp-CjcVQc9oQ2b770Zd5TcMGxWBtToS4,116
53
- civil_tools_v-0.0.2.dist-info/LICENSE,sha256=nq3TNN3UrfULANUGIRvaZAI1jUn6HlYeLxIRjJvDxCc,1088
54
- civil_tools_v-0.0.2.dist-info/METADATA,sha256=sMxhmcA6TUQynwandSb3gkIJYYxd-vHsgC3Os4QvJ9U,6184
55
- civil_tools_v-0.0.2.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
56
- civil_tools_v-0.0.2.dist-info/top_level.txt,sha256=AP0ng4FJ3z78LnGOjUzZaGRMMp-lDtw91Rlia8z--wM,11
57
- civil_tools_v-0.0.2.dist-info/RECORD,,
56
+ civil_tools_v-0.0.3.dist-info/LICENSE,sha256=nq3TNN3UrfULANUGIRvaZAI1jUn6HlYeLxIRjJvDxCc,1088
57
+ civil_tools_v-0.0.3.dist-info/METADATA,sha256=KepJhL96WNYk3DIcl27ThIj0iBJFUwud1L5obualo08,6184
58
+ civil_tools_v-0.0.3.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
59
+ civil_tools_v-0.0.3.dist-info/top_level.txt,sha256=AP0ng4FJ3z78LnGOjUzZaGRMMp-lDtw91Rlia8z--wM,11
60
+ civil_tools_v-0.0.3.dist-info/RECORD,,