3 Komitmen afcc8b467f ... 040df23d58

Pembuat SHA1 Pesan Tanggal
  raylu 040df23d58 kit: update SNF's queue and website 3 hari lalu
  raylu d028916be7 market_stats: handle ties 1 Minggu lalu
  raylu 16d1d9412e market_stats: show percentages out of 100 instead of 1 1 Minggu lalu
2 mengubah file dengan 26 tambahan dan 15 penghapusan
  1. 1 1
      cf-worker/src/kit.html
  2. 25 14
      market_stats.py

+ 1 - 1
cf-worker/src/kit.html

@@ -33,8 +33,8 @@
 		<h3>what are my other LCB buying options?</h3>
 		<a href="https://discord.com/channels/855488309802172469/1202440660246986782/1427269894226837557">HGH/craftsmanthirteen</a>'s queue is 7 months; 3.5 mil
 		<br><a href="https://discord.com/channels/855488309802172469/1337652126658330635/1337652126658330635">COSM</a>'s <a href="https://punoted.net/cosm?tab=production">queue</a> is 3 months; <a href="https://docs.google.com/forms/d/e/1FAIpQLScvObs1DmfdGZcf-L8uqraqLL0wPpMOH_et0ozST4U8Je4Caw/viewform">5.65 mil</a>
+		<br><a href="https://discord.com/channels/855488309802172469/1487382583321825360/1492910834387648604">SNF/cptwaffles</a>'s queue is 4 weeks; <a href="https://stokovich.github.io/prun-shipyard/">6.42 mil</a>
 		<br><a href="https://discord.com/channels/855488309802172469/1289570727644631160/1499999925444804710">GTU/schaitr</a>'s <a href="https://docs.google.com/spreadsheets/d/1n3IuCfAuEOFcHc18Fw-9CeGJADU01IKZqwsdMdEvmlM">queue</a> is 3 weeks; <a href="https://schaitr.github.io/GTU-Shipbuilding/">5.94-6.58 mil (ENG, SSL, SFL, BHP)</a>
-		<br><a href="https://discord.com/channels/855488309802172469/1487382583321825360/1492910834387648604">SNF/cptwaffles</a>'s queue is 1 week; 6.3 mil
 		<br><a href="https://discord.com/channels/855488309802172469/1536792900988440606/1536792900988440606">silentreaper</a>'s queue is 1 week; <a href="https://reaper-tech-shipyards.vercel.app">7 mil</a>
 		<br><a href="https://discord.com/channels/855488309802172469/1500400845005787146/1503067909000265728">OOG</a> has no queue; <a href="https://oogcapitalmanagement.com/shipbuilding/">7.2 mil (STS)</a>
 

+ 25 - 14
market_stats.py

@@ -52,33 +52,44 @@ def analyze_markets(prices: typing.Sequence[market.RawPrice], date: datetime.dat
 			continue
 		markets[price['MaterialTicker']].append(price)
 
-	markets_with_trades = ranking = ic1_lowest = ic1_zero = gap = 0
+	markets_with_trades = total_rank = ic1_lowest = ic1_zero = gap = 0
 	for mat, mat_prices in markets.items():
-		mat_prices.sort(key=lambda p: (p['Traded7D'] or 0))
-		if mat_prices[-1]['Traded7D'] == None:
+		# find IC1's Traded7D rank among the CXes
+		# group CXes by Traded7D first in case of ties
+		rankings: dict[int, list[str]] = collections.defaultdict(list)
+		for price in mat_prices:
+			rankings[price['Traded7D'] or 0].append(price['ExchangeCode'])
+		if len(rankings) == 1 and 0 in rankings: # no markets had any trades
 			continue
-		markets_with_trades += 1
-		for index, price in enumerate(mat_prices):
-			if price['ExchangeCode'] == 'IC1':
+		sorted_markets = sorted(rankings.items(), key=lambda item: item[0])
+		rank = 0
+		for _, cxes in sorted_markets:
+			if 'IC1' in cxes:
 				break
+			rank += len(cxes)
 		else:
 			raise AssertionError('IC1 not found for ' + mat)
-		ranking += index
-		if index == 0:
+		markets_with_trades += 1
+		total_rank += rank
+
+		if rank == 0:
 			ic1_lowest += 1
-			ic1_traded = mat_prices[0]['Traded7D'] or 0
-			lowest_traded = mat_prices[1]['Traded7D'] or 0
+			ic1_traded = sorted_markets[0][0]
+			if len(sorted_markets[0][1]) > 1: # another market is tied for last with us
+				lowest_traded = ic1_traded
+			else:
+				lowest_traded = sorted_markets[1][0]
 			if lowest_traded > 0:
 				if ic1_traded == 0:
 					ic1_zero += 1
 				gap += (lowest_traded - ic1_traded) / lowest_traded
-	print(f'{markets_with_trades} markets with trades, IC1 ranking {ranking}, lowest in {ic1_lowest}, zero in {ic1_zero}, gap {gap:.2f}')
+	print(f'{markets_with_trades} markets with trades, IC1 total rank {total_rank}, lowest in {ic1_lowest}, zero in {ic1_zero}, gap {gap:.2f}')
 	return {
 		'date': date.isoformat(),
-		'ranking': ranking / markets_with_trades,
-		'ic1_lowest': ic1_lowest / markets_with_trades,
+		'ranking': total_rank / markets_with_trades,
+		'ic1_lowest': ic1_lowest / markets_with_trades * 100,
 		'ic1_zero': ic1_zero,
-		'gap': gap / markets_with_trades,
+		'gap': gap / markets_with_trades * 100,
 	}
 
 def render_chart(base: altair.Chart, y: str, y_label: str, title: str) -> None: