xcpcio 0.63.6__py3-none-any.whl → 0.64.0__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.

Potentially problematic release.


This version of xcpcio might be problematic. Click here for more details.

@@ -0,0 +1,165 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Dict, List, Optional
3
+
4
+ from xcpcio.ccs.base.types import FileAttr
5
+
6
+
7
+ class BaseCCSReader(ABC):
8
+ # API Information
9
+ @abstractmethod
10
+ def get_api_info(self) -> Dict[str, Any]:
11
+ pass
12
+
13
+ @abstractmethod
14
+ def get_access(self) -> Dict[str, Any]:
15
+ pass
16
+
17
+ # Account operations
18
+ @abstractmethod
19
+ def get_accounts(self) -> List[Dict[str, Any]]:
20
+ pass
21
+
22
+ @abstractmethod
23
+ def get_account(self, account_id: str) -> Dict[str, Any]:
24
+ pass
25
+
26
+ # Contest operations
27
+ @abstractmethod
28
+ def get_contest_id(self) -> str:
29
+ pass
30
+
31
+ @abstractmethod
32
+ def get_contest(self) -> Dict[str, Any]:
33
+ pass
34
+
35
+ @abstractmethod
36
+ def get_contest_state(self) -> Dict[str, Any]:
37
+ pass
38
+
39
+ @abstractmethod
40
+ def get_contest_banner(self) -> FileAttr:
41
+ pass
42
+
43
+ @abstractmethod
44
+ def get_contest_problemset(self) -> FileAttr:
45
+ pass
46
+
47
+ # Problem operations
48
+ @abstractmethod
49
+ def get_problems(self) -> List[Dict[str, Any]]:
50
+ pass
51
+
52
+ @abstractmethod
53
+ def get_problem(self, problem_id: str) -> Dict[str, Any]:
54
+ pass
55
+
56
+ @abstractmethod
57
+ def get_problem_statement(self, problem_id: str) -> FileAttr:
58
+ pass
59
+
60
+ # Team operations
61
+ @abstractmethod
62
+ def get_teams(self) -> List[Dict[str, Any]]:
63
+ pass
64
+
65
+ @abstractmethod
66
+ def get_team(self, team_id: str) -> Dict[str, Any]:
67
+ pass
68
+
69
+ @abstractmethod
70
+ def get_team_photo(self, team_id: str) -> FileAttr:
71
+ pass
72
+
73
+ # Organization operations
74
+ @abstractmethod
75
+ def get_organizations(self) -> List[Dict[str, Any]]:
76
+ pass
77
+
78
+ @abstractmethod
79
+ def get_organization(self, organization_id: str) -> Dict[str, Any]:
80
+ pass
81
+
82
+ @abstractmethod
83
+ def get_organization_logo(self, organization_id: str) -> FileAttr:
84
+ pass
85
+
86
+ # Group operations
87
+ @abstractmethod
88
+ def get_groups(self) -> List[Dict[str, Any]]:
89
+ pass
90
+
91
+ @abstractmethod
92
+ def get_group(self, group_id: str) -> Dict[str, Any]:
93
+ pass
94
+
95
+ # Language operations
96
+ @abstractmethod
97
+ def get_languages(self) -> List[Dict[str, Any]]:
98
+ pass
99
+
100
+ @abstractmethod
101
+ def get_language(self, language_id: str) -> Dict[str, Any]:
102
+ pass
103
+
104
+ # Judgement type operations
105
+ @abstractmethod
106
+ def get_judgement_types(self) -> List[Dict[str, Any]]:
107
+ pass
108
+
109
+ @abstractmethod
110
+ def get_judgement_type(self, judgement_type_id: str) -> Dict[str, Any]:
111
+ pass
112
+
113
+ # Submission operations
114
+ @abstractmethod
115
+ def get_submissions(self) -> List[Dict[str, Any]]:
116
+ pass
117
+
118
+ @abstractmethod
119
+ def get_submission(self, submission_id: str) -> Dict[str, Any]:
120
+ pass
121
+
122
+ @abstractmethod
123
+ def get_submission_file(self, submission_id: str) -> FileAttr:
124
+ pass
125
+
126
+ # Judgement operations
127
+ @abstractmethod
128
+ def get_judgements(self, submission_id: Optional[str] = None) -> List[Dict[str, Any]]:
129
+ pass
130
+
131
+ @abstractmethod
132
+ def get_judgement(self, judgement_id: str) -> Dict[str, Any]:
133
+ pass
134
+
135
+ # Run operations
136
+ @abstractmethod
137
+ def get_runs(self, judgement_id: Optional[str] = None) -> List[Dict[str, Any]]:
138
+ pass
139
+
140
+ @abstractmethod
141
+ def get_run(self, run_id: str) -> Dict[str, Any]:
142
+ pass
143
+
144
+ # Clarification operations
145
+ @abstractmethod
146
+ def get_clarifications(self) -> List[Dict[str, Any]]:
147
+ pass
148
+
149
+ @abstractmethod
150
+ def get_clarification(self, clarification_id: str) -> Dict[str, Any]:
151
+ pass
152
+
153
+ # Award operations
154
+ @abstractmethod
155
+ def get_awards(self) -> List[Dict[str, Any]]:
156
+ pass
157
+
158
+ @abstractmethod
159
+ def get_award(self, award_id: str) -> Dict[str, Any]:
160
+ pass
161
+
162
+ # Event Feed operations
163
+ @abstractmethod
164
+ def get_event_feed(self, since_token: Optional[str] = None) -> List[Dict[str, Any]]:
165
+ pass
@@ -0,0 +1,331 @@
1
+ import bisect
2
+ import json
3
+ import logging
4
+ from collections import defaultdict
5
+ from pathlib import Path
6
+ from typing import Any, Dict, List, Optional, Union
7
+
8
+ from fastapi import HTTPException
9
+
10
+ from xcpcio.ccs.base.types import FileAttr
11
+ from xcpcio.ccs.reader.base_ccs_reader import BaseCCSReader
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class ContestPackageReader(BaseCCSReader):
17
+ def __init__(self, contest_package_dir: Path):
18
+ self.contest_package_dir = contest_package_dir
19
+ if not self.contest_package_dir.exists():
20
+ raise ValueError(f"Contest package directory does not exist: {contest_package_dir}")
21
+
22
+ self._load_indexes()
23
+
24
+ def _create_index_by_id(self, data: List[Dict[str, Any]], id_name: str) -> Dict[str, List[Dict]]:
25
+ res = defaultdict(list)
26
+ for item in data:
27
+ res[item[id_name]].append(item)
28
+ return res
29
+
30
+ def _load_json_file(self, filepath: str) -> Union[Dict[str, Any], List[Any]]:
31
+ full_path = self.contest_package_dir / filepath
32
+ try:
33
+ with open(full_path, "r", encoding="utf-8") as f:
34
+ return json.load(f)
35
+ except FileNotFoundError:
36
+ raise HTTPException(status_code=404, detail=f"File not found: {filepath}")
37
+ except json.JSONDecodeError as e:
38
+ raise HTTPException(status_code=500, detail=f"Invalid JSON in file {filepath}: {e}")
39
+
40
+ def _load_ndjson_file(self, filepath: str) -> List[Dict[str, Any]]:
41
+ full_path = self.contest_package_dir / filepath
42
+ try:
43
+ data = list()
44
+ with open(full_path, "r", encoding="utf-8") as f:
45
+ for line in f.readlines():
46
+ data.append(json.loads(line))
47
+ return data
48
+ except FileNotFoundError:
49
+ raise HTTPException(status_code=404, detail=f"File not found: {filepath}")
50
+ except json.JSONDecodeError as e:
51
+ raise HTTPException(status_code=500, detail=f"Invalid JSON in file {filepath}: {e}")
52
+
53
+ def _load_indexes(self) -> None:
54
+ self.access = self._load_json_file("access.json")
55
+
56
+ self.accounts = self._load_json_file("accounts.json")
57
+ self.accounts_by_id = {account["id"] for account in self.accounts}
58
+
59
+ self.api_info = self._load_json_file("api.json")
60
+
61
+ self.awards = self._load_json_file("awards.json")
62
+ self.awards_by_id = {award["id"] for award in self.awards}
63
+
64
+ self.clarifications = self._load_json_file("clarifications.json")
65
+ self.clarifications_by_id = {clarification["id"] for clarification in self.clarifications}
66
+
67
+ self.contest = self._load_json_file("contest.json")
68
+ self.contest_state = self._load_json_file("state.json")
69
+
70
+ self.groups = self._load_json_file("groups.json")
71
+ self.groups_by_id = {group["id"]: group for group in self.groups}
72
+
73
+ self.judgement_types = self._load_json_file("judgement-types.json")
74
+ self.judgement_types_by_id = {judgement_type["id"] for judgement_type in self.judgement_types}
75
+
76
+ self.judgements = self._load_json_file("judgements.json")
77
+ self.judgements_by_id = {judgement["id"] for judgement in self.judgements}
78
+ self.judgements_by_submission_id = self._create_index_by_id(self.judgements, "submission_id")
79
+
80
+ self.languages = self._load_json_file("languages.json")
81
+ self.languages_by_id = {language["id"] for language in self.languages}
82
+
83
+ self.organizations = self._load_json_file("organizations.json")
84
+ self.organizations_by_id = {org["id"]: org for org in self.organizations}
85
+
86
+ self.problems = self._load_json_file("problems.json")
87
+ self.problems_by_id = {problem["id"]: problem for problem in self.problems}
88
+
89
+ self.runs = self._load_json_file("runs.json")
90
+ self.runs_by_id = {run["id"] for run in self.runs}
91
+ self.runs_by_judgement_id = self._create_index_by_id(self.runs, "judgement_id")
92
+
93
+ self.submissions = self._load_json_file("submissions.json")
94
+ self.submissions_by_id = {submission["id"]: submission for submission in self.submissions}
95
+
96
+ self.teams = self._load_json_file("teams.json")
97
+ self.teams_by_id = {team["id"]: team for team in self.teams}
98
+
99
+ self.event_feed = self._load_ndjson_file("event-feed.ndjson")
100
+ self.event_feed_tokens = [event["token"] for event in self.event_feed]
101
+
102
+ self.contest_id = self.contest["id"]
103
+
104
+ def _get_file_attr(self, expected_href: str, base_path: Path, files: List[Dict]) -> FileAttr:
105
+ for file in files:
106
+ href = file["href"]
107
+ if href == expected_href:
108
+ filename = file["filename"]
109
+ mime_type = file["mime"]
110
+ filepath: Path = base_path / filename
111
+ if not filepath.exists():
112
+ raise FileNotFoundError(f"File not found: {filepath}")
113
+ return FileAttr(path=filepath, media_type=mime_type, name=filename)
114
+ raise KeyError(f"Href not found: {expected_href}")
115
+
116
+ # API Information
117
+ def get_api_info(self) -> Dict[str, Any]:
118
+ return self.api_info
119
+
120
+ def get_access(self) -> Dict[str, Any]:
121
+ return self.access
122
+
123
+ # Account operations
124
+ def get_accounts(self) -> List[Dict[str, Any]]:
125
+ return self.accounts
126
+
127
+ def get_account(self, account_id: str) -> Dict[str, Any]:
128
+ if account_id not in self.accounts_by_id:
129
+ raise HTTPException(status_code=404, detail=f"Account {account_id} not found")
130
+ return self.accounts_by_id[account_id]
131
+
132
+ # Contest operations
133
+ def get_contest_id(self) -> str:
134
+ return self.contest["id"]
135
+
136
+ def get_contest(self) -> Dict[str, Any]:
137
+ return self.contest
138
+
139
+ def get_contest_state(self) -> Dict[str, Any]:
140
+ return self.contest_state
141
+
142
+ def get_contest_banner(self) -> FileAttr:
143
+ expected_href = f"contests/{self.contest_id}/banner"
144
+ base_path = self.contest_package_dir / "contest"
145
+ files = self.contest.get("banner", [])
146
+
147
+ try:
148
+ return self._get_file_attr(expected_href, base_path, files)
149
+ except Exception as e:
150
+ raise HTTPException(status_code=404, detail=f"Banner not found. [contest_id={self.contest_id}] [err={e}]")
151
+
152
+ def get_contest_problemset(self) -> FileAttr:
153
+ expected_href = f"contests/{self.contest_id}/problemset"
154
+ base_path = self.contest_package_dir / "contest"
155
+ files = self.contest.get("problemset", [])
156
+
157
+ try:
158
+ return self._get_file_attr(expected_href, base_path, files)
159
+ except Exception as e:
160
+ raise HTTPException(
161
+ status_code=404, detail=f"Problemset not found. [contest_id={self.contest_id}] [err={e}]"
162
+ )
163
+
164
+ # Problem operations
165
+ def get_problems(self) -> List[Dict[str, Any]]:
166
+ return self.problems
167
+
168
+ def get_problem(self, problem_id: str) -> Dict[str, Any]:
169
+ if problem_id not in self.problems_by_id:
170
+ raise HTTPException(status_code=404, detail=f"Problem {problem_id} not found")
171
+ return self.problems_by_id[problem_id]
172
+
173
+ def get_problem_statement(self, problem_id: str) -> FileAttr:
174
+ expected_href = f"contests/{self.contest_id}/problems/{problem_id}/statement"
175
+ base_path = self.contest_package_dir / "problems" / problem_id
176
+ files = self.get_problem(problem_id).get("statement", [])
177
+
178
+ try:
179
+ return self._get_file_attr(expected_href, base_path, files)
180
+ except Exception as e:
181
+ raise HTTPException(
182
+ status_code=404,
183
+ detail=f"Problem statement not found. [contest_id={self.contest_id}] [problem_id={problem_id}] [err={e}]",
184
+ )
185
+
186
+ # Team operations
187
+ def get_teams(self) -> List[Dict[str, Any]]:
188
+ return self.teams
189
+
190
+ def get_team(self, team_id: str) -> Dict[str, Any]:
191
+ if team_id not in self.teams_by_id:
192
+ raise HTTPException(status_code=404, detail=f"Team {team_id} not found")
193
+ return self.teams_by_id[team_id]
194
+
195
+ def get_team_photo(self, team_id: str) -> FileAttr:
196
+ expected_href = f"contests/{self.contest_id}/teams/{team_id}/photo"
197
+ base_path = self.contest_package_dir / "teams" / team_id
198
+ files = self.get_team(team_id).get("photo", [])
199
+
200
+ try:
201
+ return self._get_file_attr(expected_href, base_path, files)
202
+ except Exception as e:
203
+ raise HTTPException(
204
+ status_code=404,
205
+ detail=f"Team photo not found. [contest_id={self.contest_id}] [team_id={team_id}] [err={e}]",
206
+ )
207
+
208
+ # Organization operations
209
+ def get_organizations(self) -> List[Dict[str, Any]]:
210
+ return self.organizations
211
+
212
+ def get_organization(self, organization_id: str) -> Dict[str, Any]:
213
+ if organization_id not in self.organizations_by_id:
214
+ raise HTTPException(status_code=404, detail=f"Organization {organization_id} not found")
215
+ return self.organizations_by_id[organization_id]
216
+
217
+ def get_organization_logo(self, organization_id: str) -> FileAttr:
218
+ expected_href = f"contests/{self.contest_id}/organizations/{organization_id}/logo"
219
+ base_path = self.contest_package_dir / "organizations" / organization_id
220
+ files = self.get_organization(organization_id).get("logo", [])
221
+
222
+ try:
223
+ return self._get_file_attr(expected_href, base_path, files)
224
+ except Exception as e:
225
+ raise HTTPException(
226
+ status_code=404,
227
+ detail=f"Organization logo not found. [contest_id={self.contest_id}] [organization_id={organization_id}] [err={e}]",
228
+ )
229
+
230
+ # Group operations
231
+ def get_groups(self) -> List[Dict[str, Any]]:
232
+ return self.groups
233
+
234
+ def get_group(self, group_id: str) -> Dict[str, Any]:
235
+ if group_id not in self.groups_by_id:
236
+ raise HTTPException(status_code=404, detail=f"Group {group_id} not found")
237
+ return self.groups_by_id[group_id]
238
+
239
+ # Language operations
240
+ def get_languages(self) -> List[Dict[str, Any]]:
241
+ return self.languages
242
+
243
+ def get_language(self, language_id: str) -> Dict[str, Any]:
244
+ if language_id not in self.languages_by_id:
245
+ raise HTTPException(status_code=404, detail=f"Language {language_id} not found")
246
+ return self.languages_by_id[language_id]
247
+
248
+ # Judgement type operations
249
+ def get_judgement_types(self) -> List[Dict[str, Any]]:
250
+ return self.judgement_types
251
+
252
+ def get_judgement_type(self, judgement_type_id: str) -> Dict[str, Any]:
253
+ if judgement_type_id not in self.judgement_types_by_id:
254
+ raise HTTPException(status_code=404, detail=f"Judgement type {judgement_type_id} not found")
255
+ return self.judgement_types_by_id[judgement_type_id]
256
+
257
+ # Submission operations
258
+ def get_submissions(self) -> List[Dict[str, Any]]:
259
+ return self.submissions
260
+
261
+ def get_submission(self, submission_id: str) -> Dict[str, Any]:
262
+ if submission_id not in self.submissions_by_id:
263
+ raise HTTPException(status_code=404, detail=f"Submission {submission_id} not found")
264
+ return self.submissions_by_id[submission_id]
265
+
266
+ def get_submission_file(self, submission_id: str) -> FileAttr:
267
+ expected_href = f"contests/{self.contest_id}/submissions/{submission_id}/files"
268
+ base_path = self.contest_package_dir / "submissions" / submission_id
269
+ files = self.get_submission(submission_id).get("files", [])
270
+
271
+ try:
272
+ return self._get_file_attr(expected_href, base_path, files)
273
+ except Exception as e:
274
+ raise HTTPException(
275
+ status_code=404,
276
+ detail=f"Submission file not found. [contest_id={self.contest_id}] [submission_id={submission_id}] [err={e}]",
277
+ )
278
+
279
+ # Judgement operations
280
+ def get_judgements(self, submission_id: Optional[str] = None) -> List[Dict[str, Any]]:
281
+ if submission_id is not None:
282
+ if submission_id not in self.judgements_by_submission_id:
283
+ raise HTTPException(status_code=404, detail=f"Submission id not found: {submission_id}")
284
+ return self.judgements_by_submission_id[submission_id]
285
+
286
+ return self.judgements
287
+
288
+ def get_judgement(self, judgement_id: str) -> Dict[str, Any]:
289
+ if judgement_id not in self.judgements_by_id:
290
+ raise HTTPException(status_code=404, detail=f"Judgement {judgement_id} not found")
291
+ return self.judgements_by_id[judgement_id]
292
+
293
+ # Run operations
294
+ def get_runs(self, judgement_id: Optional[str] = None) -> List[Dict[str, Any]]:
295
+ if judgement_id is not None:
296
+ if judgement_id not in self.runs_by_judgement_id:
297
+ raise HTTPException(status_code=404, detail=f"Judgement id not found: {judgement_id}")
298
+ return self.runs_by_judgement_id[judgement_id]
299
+
300
+ return self.runs
301
+
302
+ def get_run(self, run_id: str) -> Dict[str, Any]:
303
+ if run_id not in self.runs_by_id:
304
+ raise HTTPException(status_code=404, detail=f"Run {run_id} not found")
305
+ return self.runs_by_id[run_id]
306
+
307
+ # Clarification operations
308
+ def get_clarifications(self) -> List[Dict[str, Any]]:
309
+ return self.clarifications
310
+
311
+ def get_clarification(self, clarification_id: str) -> Dict[str, Any]:
312
+ if clarification_id not in self.clarifications_by_id:
313
+ raise HTTPException(status_code=404, detail=f"Clarification {clarification_id} not found")
314
+ return self.clarifications_by_id[clarification_id]
315
+
316
+ # Award operations
317
+ def get_awards(self) -> List[Dict[str, Any]]:
318
+ return self.awards
319
+
320
+ def get_award(self, award_id: str) -> Dict[str, Any]:
321
+ if award_id not in self.awards_by_id:
322
+ raise HTTPException(status_code=404, detail=f"Award {award_id} not found")
323
+ return self.awards_by_id[award_id]
324
+
325
+ # Event Feed operations
326
+ def get_event_feed(self, since_token: Optional[str] = None) -> List[Dict[str, Any]]:
327
+ if since_token is None:
328
+ return self.event_feed
329
+
330
+ idx = bisect.bisect_left(self.event_feed_tokens, since_token)
331
+ return self.event_feed[idx:]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xcpcio
3
- Version: 0.63.6
3
+ Version: 0.64.0
4
4
  Summary: xcpcio python lib
5
5
  Project-URL: homepage, https://github.com/xcpcio/xcpcio
6
6
  Project-URL: documentation, https://github.com/xcpcio/xcpcio
@@ -25,6 +25,7 @@ Requires-Dist: pyyaml>=6.0.0
25
25
  Requires-Dist: semver>=3.0.0
26
26
  Requires-Dist: tenacity>=8.0.0
27
27
  Requires-Dist: uvicorn>=0.36.0
28
+ Requires-Dist: zstandard>=0.25.0
28
29
  Description-Content-Type: text/markdown
29
30
 
30
31
  # xcpcio-python
@@ -0,0 +1,39 @@
1
+ xcpcio/__init__.py,sha256=kjd6itqBRSQ-OT83qUJXHt81KQQDRUtaIuykzfaWXLM,121
2
+ xcpcio/__version__.py,sha256=klqfiPl7r99QoDZy8_HzKScRlEEWVa3Svby8c3yeAsY,172
3
+ xcpcio/constants.py,sha256=MjpAgNXiBlUsx1S09m7JNT-nekNDR-aE6ggvGL3fg0I,2297
4
+ xcpcio/types.py,sha256=AkYby2haJgxwtozlgaPMG2ryAZdvsSc3sH-p6qXcM4g,6575
5
+ xcpcio/ccs/__init__.py,sha256=LSoKFblEuSoIVBYcUxOFF8fn2bH2R6kSg9xNrBfzC0g,99
6
+ xcpcio/ccs/contest_archiver.py,sha256=ICogyPzKfFRoO7J5D2Eu-3JwIirC3etMev7hyTjn4z8,16198
7
+ xcpcio/ccs/api_server/__init__.py,sha256=ASvVJ_ibGkXFDSNmy05eb9gESXRS8hjYHCrBecSnaS0,174
8
+ xcpcio/ccs/api_server/dependencies.py,sha256=cbLHcP91SaRBj2W9OfC0yCQ1fasI2DofxGUhPPNs3F8,1518
9
+ xcpcio/ccs/api_server/server.py,sha256=3gft3MqDXvKWug5UCLhdV681bcQMRrewDkwQ7qSPtRU,2598
10
+ xcpcio/ccs/api_server/routes/__init__.py,sha256=uz65H4L5Wzef7QPi5PsLQM1xbMdG6FoZ0Np0y039_2k,1537
11
+ xcpcio/ccs/api_server/routes/access.py,sha256=O-RGLmgLNBQ-ccu8rlHOgonTjl02fYOdi3VTsUa-T0w,434
12
+ xcpcio/ccs/api_server/routes/accounts.py,sha256=nAwiIz-y4fGmqHBniMuQifk9jVt4i9YPZWBB7w40q5Q,994
13
+ xcpcio/ccs/api_server/routes/awards.py,sha256=gBPSFlDj6PM6Poys6JbO7VMsfCljKz6QrTjKEqQcS8w,957
14
+ xcpcio/ccs/api_server/routes/clarifications.py,sha256=vvMNMvQkZTOn1VJ8C5U86gpIkN3yNrxBll1VMTJjzQg,1046
15
+ xcpcio/ccs/api_server/routes/contests.py,sha256=VbvegfP5ZnVNKdqoHmy7_Wd2L6xEBqON7UD2OQ6sQ8A,2979
16
+ xcpcio/ccs/api_server/routes/general.py,sha256=xLH-sqyeC4dSd6SUYpjg-w-1ZtmSqZAgIupoVOyYwD4,763
17
+ xcpcio/ccs/api_server/routes/groups.py,sha256=kWKFFty2iWckMN-j6G3NbgMVKCPQ478_mYKrYsHXgMA,949
18
+ xcpcio/ccs/api_server/routes/judgement_types.py,sha256=S3Dt0VYjntVBQBvLYhJGcDNSy7O8Zh7b7NSfrronZSU,1057
19
+ xcpcio/ccs/api_server/routes/judgements.py,sha256=3w0LHYbZazli_v587l98U23r5PuolRs_vtbNLMwgjTU,1127
20
+ xcpcio/ccs/api_server/routes/languages.py,sha256=2BYqTaSBWx0E5XlaTjofElLb7z4HTsVs3rrozdyqz0s,985
21
+ xcpcio/ccs/api_server/routes/organizations.py,sha256=6xMl0Iqo7pjLaJbR7L1NWwo8JXwnXhH2O8hJKiLoRa0,1712
22
+ xcpcio/ccs/api_server/routes/problems.py,sha256=XAhXkShHwewZdugsffLj1UxvFNSorrxc-PyZymdBQTY,1632
23
+ xcpcio/ccs/api_server/routes/runs.py,sha256=1L6fo1KPcDeKwOEkTxCwEetmyfNKY_Z0uxATqBJftIs,1046
24
+ xcpcio/ccs/api_server/routes/submissions.py,sha256=ByVX_wzab0Q9EHFmuE8JQtikvboMXtt_kXecEy6yiRc,1675
25
+ xcpcio/ccs/api_server/routes/teams.py,sha256=euDs-GDHLqmJS3zPTNxm9LfKXQYEuhwAlX-BF2tcrk4,1556
26
+ xcpcio/ccs/api_server/services/__init__.py,sha256=WQLNrLVomhtICl8HlFYaCoRewIHVZfUiiwrSBUOOWDg,171
27
+ xcpcio/ccs/api_server/services/contest_service.py,sha256=Jmt7h4rQoZLXPAkHx3FdQNsRtYOPpdSOlh7QA41nIm4,7467
28
+ xcpcio/ccs/base/__init__.py,sha256=JYKVtcQG-VGM2OfCg6VhxcXCeCp7r2zxpg_7s9AThS0,39
29
+ xcpcio/ccs/base/types.py,sha256=NfAG-XJjex7p2DfFTRecLWhmwpeO8Ul42nNMnZH39sM,137
30
+ xcpcio/ccs/model/__init__.py,sha256=cZE1q5JY-iHDEKZpsx0UZaMhH-23H4oAHaYOkW7dZ5s,43
31
+ xcpcio/ccs/model/model_2023_06/__init__.py,sha256=OmDQZqmigBpL64LXk5lIOGoQ3Uqis8-2z6qQpOO5aJc,167
32
+ xcpcio/ccs/model/model_2023_06/model.py,sha256=bVMDWpJTwPSpz1fHPxWrWerxCBIboH3LKVZpIZGQ2pY,15287
33
+ xcpcio/ccs/reader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
+ xcpcio/ccs/reader/base_ccs_reader.py,sha256=fS7M0hD3-3PAEV7EYyorVZsBhD4HtABkQeV4fXNldhA,3912
35
+ xcpcio/ccs/reader/contest_package_reader.py,sha256=DPuKp3eptRNMi0-Ssx_K2roN5_0xXILMltucWy1NTPI,14173
36
+ xcpcio-0.64.0.dist-info/METADATA,sha256=1hiCdfGBJXTXTNnDe0AGnS-BoFWv4Q_W8LmbNjSMPvU,1112
37
+ xcpcio-0.64.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
38
+ xcpcio-0.64.0.dist-info/entry_points.txt,sha256=qvzh8oDJxIHqTN-rg2lRN6xR99AqxbWnlAQI7uzDibI,59
39
+ xcpcio-0.64.0.dist-info/RECORD,,
@@ -1,33 +0,0 @@
1
- xcpcio/__init__.py,sha256=kjd6itqBRSQ-OT83qUJXHt81KQQDRUtaIuykzfaWXLM,121
2
- xcpcio/__version__.py,sha256=rmZgql2iMibrRXQ70oij5TmONsjXyGZIxE3EUzW1_1E,172
3
- xcpcio/constants.py,sha256=MjpAgNXiBlUsx1S09m7JNT-nekNDR-aE6ggvGL3fg0I,2297
4
- xcpcio/types.py,sha256=AkYby2haJgxwtozlgaPMG2ryAZdvsSc3sH-p6qXcM4g,6575
5
- xcpcio/ccs/__init__.py,sha256=LSoKFblEuSoIVBYcUxOFF8fn2bH2R6kSg9xNrBfzC0g,99
6
- xcpcio/ccs/contest_archiver.py,sha256=FKpUn1IGfa-UNf63OJ5eff7rxOEqXCvFYRLsvkMbUJc,16203
7
- xcpcio/ccs/api_server/__init__.py,sha256=ASvVJ_ibGkXFDSNmy05eb9gESXRS8hjYHCrBecSnaS0,174
8
- xcpcio/ccs/api_server/dependencies.py,sha256=5nosGVwY-3Mq7eK9C5ZOMEJFozzzw_kLlpCraFbJ9wY,1225
9
- xcpcio/ccs/api_server/server.py,sha256=3gft3MqDXvKWug5UCLhdV681bcQMRrewDkwQ7qSPtRU,2598
10
- xcpcio/ccs/api_server/routes/__init__.py,sha256=imTyDjc9Md3OIr7GniHi3i1vmfzSTKppuUjVREtd8b4,1461
11
- xcpcio/ccs/api_server/routes/access.py,sha256=8f21NmvVLaFopb5q4MnifOHbhadDZuNHr0BIYc9nmqY,579
12
- xcpcio/ccs/api_server/routes/awards.py,sha256=uj56ty2k7N5KXfQuWTvvTXSa7HO29CUfEhO8S85hlM0,1069
13
- xcpcio/ccs/api_server/routes/clarifications.py,sha256=JX7FNbv_4mRdpuV0aSzGwjjmW-4SwTbmAOlm51MNpf4,1644
14
- xcpcio/ccs/api_server/routes/contests.py,sha256=bJeMaGegei59rD-5YE0ptYcNsPdJqc73KnntRpShzZk,2560
15
- xcpcio/ccs/api_server/routes/general.py,sha256=9WsnjlomsU13vvozOVHSRIzgReuLGzPln3xwDb8i-gY,933
16
- xcpcio/ccs/api_server/routes/groups.py,sha256=8hOT_2rz329M_7hcfggRxLU-g8aV2xp6w3aMYlfOPNs,1087
17
- xcpcio/ccs/api_server/routes/judgement_types.py,sha256=pMOFBQ1LqKhCTLNBGzopCOEmTnWsuVg67dTuItJaCsM,1268
18
- xcpcio/ccs/api_server/routes/judgements.py,sha256=9GMaEkD8erhqaSItlZQdLzKz-1XL7MD2SQinnD_CZFg,1339
19
- xcpcio/ccs/api_server/routes/languages.py,sha256=DUNRd3q_Hm5F8-3nCiAMpqqxzG_9zcU5_N8ACefqjOE,1176
20
- xcpcio/ccs/api_server/routes/organizations.py,sha256=fWnKTCmxd3c1leYsRuJHuuTs0CZr-l_-Jl-8_wY_Ojk,2889
21
- xcpcio/ccs/api_server/routes/problems.py,sha256=0Ba3fz09UfTGYmYYYJYFGmIpgIvJaa1Fg-5pcLcxEMY,2774
22
- xcpcio/ccs/api_server/routes/runs.py,sha256=uBPeM5ChI3LxR__pBSyDxsbcE4NyL6eKVdvF4TEOk5g,1248
23
- xcpcio/ccs/api_server/routes/submissions.py,sha256=81-KbQLUKCqgGE-aCTO7-Pg2QyTJc_Mu_Ys8N0oF1tU,3161
24
- xcpcio/ccs/api_server/routes/teams.py,sha256=y_aJykzgewmOQtXOJe2s0s7DQmnKjD3805Q5VTcdlIQ,2725
25
- xcpcio/ccs/api_server/services/__init__.py,sha256=WQLNrLVomhtICl8HlFYaCoRewIHVZfUiiwrSBUOOWDg,171
26
- xcpcio/ccs/api_server/services/contest_service.py,sha256=EbSDrkVg18Th9kAuYAin4InHCOI7hWkkDJR1u1xlEtk,16186
27
- xcpcio/ccs/model/__init__.py,sha256=cZE1q5JY-iHDEKZpsx0UZaMhH-23H4oAHaYOkW7dZ5s,43
28
- xcpcio/ccs/model/model_2023_06/__init__.py,sha256=OmDQZqmigBpL64LXk5lIOGoQ3Uqis8-2z6qQpOO5aJc,167
29
- xcpcio/ccs/model/model_2023_06/model.py,sha256=bVMDWpJTwPSpz1fHPxWrWerxCBIboH3LKVZpIZGQ2pY,15287
30
- xcpcio-0.63.6.dist-info/METADATA,sha256=uEBCmgoTkMCCrO-zLZGdzDjhYb9n51mabFs4lwEV0II,1079
31
- xcpcio-0.63.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
32
- xcpcio-0.63.6.dist-info/entry_points.txt,sha256=qvzh8oDJxIHqTN-rg2lRN6xR99AqxbWnlAQI7uzDibI,59
33
- xcpcio-0.63.6.dist-info/RECORD,,