2
0

2 Коммиты 83b9426a2a ... d9e10643d4

Автор SHA1 Сообщение Дата
  raylu d9e10643d4 grants: base/volume stats 3 дней назад
  raylu 8e354216f5 grants 3 дней назад
5 измененных файлов с 76 добавлено и 8 удалено
  1. 1 1
      company.py
  2. 15 5
      integration.py
  3. 1 1
      mat_competitors.py
  4. 2 1
      punoted/contracts.py
  5. 57 0
      punoted/grants.py

+ 1 - 1
company.py

@@ -21,7 +21,7 @@ def main() -> None:
 	print()
 
 	experts = mat_expertise()
-	company_report = integration.pmmg_monthly_report()[company['CompanyId']]
+	company_report = integration.pmmg_monthly_report()['individual'][company['CompanyId']]
 	report_by_expertise: dict[str | None, dict[str, int]] = collections.defaultdict(dict)
 	for mat, production in company_report.items():
 		expertise = experts.get(mat)

+ 15 - 5
integration.py

@@ -14,7 +14,7 @@ def main() -> None:
 	mat = sys.argv[1]
 
 	recipes: list[roi.Recipe] = cache.get('https://api.prunplanner.org/data/recipes/')
-	companies = pmmg_monthly_report()
+	companies = pmmg_monthly_report()['individual']
 
 	print(mat, '→')
 	wrought = (recipe for recipe in recipes
@@ -63,7 +63,12 @@ def main() -> None:
 			alt = f' ({recipe_count} recipes)'
 		print(f'{output_mat:3}: {total:8,.0f}{alt}')
 
-def pmmg_monthly_report() -> dict[str, dict[str, CompanyOutput]]:
+def pmmg_monthly_report() -> CompanyData:
+	last_month = pmmg_month()
+	print('getting report for', last_month)
+	return cache.get(f'https://prun.raylu.net/stats/data/company-data-{last_month}.json', expiry=cache.ONE_DAY)
+
+def pmmg_month() -> str:
 	report_constants = cache.get('https://git.raylu.net/raylu/prunstats/raw/main/src/staticData/constants.ts',
 			json=False, expiry=cache.ONE_DAY)
 	# export const months = ["mar25", "apr25", ..., "dec25", "jan26"];
@@ -71,9 +76,14 @@ def pmmg_monthly_report() -> dict[str, dict[str, CompanyOutput]]:
 	assert match
 	months_str = match.group(1)
 	months = [m.strip().strip('"') for m in months_str.split(',')]
-	last_month = months[-1]
-	print('getting report for', last_month)
-	return cache.get(f'https://prun.raylu.net/stats/data/company-data-{last_month}.json', expiry=cache.ONE_DAY)['individual']
+	return months[-1]
+
+class CompanyData(typing.TypedDict):
+	totals: dict[str, CompanyTotal]
+	individual: dict[str, dict[str, CompanyOutput]]
+
+class CompanyTotal(typing.TypedDict):
+	volume: float
 
 class CompanyOutput(typing.TypedDict):
 	amount: int

+ 1 - 1
mat_competitors.py

@@ -43,7 +43,7 @@ def main() -> None:
 		for company_id, d in cache.get('https://prun.raylu.net/stats/data/knownCompanies.json', expiry=cache.ONE_DAY).items()}
 
 	competitors: list[Competitor] = []
-	for company_id, co_production in integration.pmmg_monthly_report().items():
+	for company_id, co_production in integration.pmmg_monthly_report()['individual'].items():
 		if (mat_production := co_production.get(ticker)) is None:
 			continue
 		if planet_ids := coid_bases.get(company_id):

+ 2 - 1
punoted/contracts.py

@@ -28,7 +28,8 @@ def main() -> None:
 				case 'PAYMENT':
 					print('\t', condition['Amount'], condition['Currency'])
 				case 'PROVISION_SHIPMENT' | 'PICKUP_SHIPMENT' | 'DELIVERY_SHIPMENT' | 'REPUTATION' | 'EXPLORATION' | 'REPAIR_SHIP' \
-						| 'PROVISION' | 'LOAN_PAYOUT' | 'LOAN_INSTALLMENT':
+						| 'PROVISION' | 'LOAN_PAYOUT' | 'LOAN_INSTALLMENT' | 'WORKFORCE_PROGRAM_PAYMENT' | 'WORKFORCE_PROGRAM_START' \
+						| 'CONSTRUCT_SHIP':
 					pass
 				case _:
 					raise AssertionError('unhandled condition type ' + condition['Type'])

+ 57 - 0
punoted/grants.py

@@ -0,0 +1,57 @@
+import sys
+import typing
+
+import httpx
+
+import cache
+from config import config
+import integration
+
+def main() -> None:
+	stats_month = integration.pmmg_month()
+	coid_totals = integration.pmmg_monthly_report()['totals']
+	bases = cache.get(f'https://prun.raylu.net/stats/data/base-data-{stats_month}.json', expiry=cache.ONE_DAY)
+
+	for co in iter_grants():
+		if co is None:
+			print('\n')
+			continue
+		company = cache.get('https://rest.fnar.net/company/code/' + co)
+		co_id = company['CompanyId']
+		username = company['UserName']
+		try:
+			url = 'https://prun.raylu.net/stats/?type=compTotals&chartType=treemap&metric=volume&group=company&companyName=' + username
+			print(f'\t{bases[co_id]["bases"]} bases\t{coid_totals[co_id]["volume"]:,.0f} volume\t{url}\n')
+		except KeyError:
+			print(f'\tno stats for {username}\n')
+
+def iter_grants() -> typing.Iterator[str | None]:
+	(username,) = sys.argv[1:]
+	params = {'username': username, 'status': 'TERMINATED', 'limit': 200, 'page': 1}
+	while True:
+		(data,) = httpx.get(f'https://api.punoted.net/v1/contracts/?username={username}&limit=200', params=params,
+				headers={'X-Data-Token': config.punoted_api_key}).raise_for_status().json()
+		data['Contracts'].sort(key=lambda c: c['DateEpochMs'])
+		for contract in data['Contracts']:
+			conditions = contract['Conditions']
+			if len(conditions) != 2:
+				continue
+			payment = None
+			if conditions[0]['Type'] == 'PAYMENT' and conditions[1]['Type'] == 'DELIVERY':
+				payment, delivery = conditions
+				if payment['Amount'] < 100000 or payment['Amount'] > 1000000 or delivery['Address'] != 'JY-313f (JY-313)':
+					continue
+			elif conditions[0]['Type'] == 'LOAN_PAYOUT' and conditions[1]['Type'] == 'LOAN_INSTALLMENT':
+				payment, installment = conditions
+				if payment['Amount'] < 100000 or payment['Amount'] > 1000000:
+					continue
+			if payment is not None and payment['Status'] == 'FULFILLED':
+				print(f'{payment["Amount"]:9,} {payment["Currency"]}', contract['Status'], contract['Timestamp'],
+						contract['PartnerCode'], contract['PartnerName'])
+				yield contract['PartnerCode']
+		if len(data['Contracts']) < 200:
+			break
+		params['page'] += 1
+
+if __name__ == '__main__':
+	main()