be-components 1.1.7 → 1.1.9

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.
Files changed (42) hide show
  1. package/lib/commonjs/Squares/api/index.js +604 -0
  2. package/lib/commonjs/Squares/api/index.js.map +1 -1
  3. package/lib/commonjs/Squares/components/BidForm.js +0 -1
  4. package/lib/commonjs/Squares/components/BidForm.js.map +1 -1
  5. package/lib/commonjs/Squares/components/BoardStats.js +0 -22
  6. package/lib/commonjs/Squares/components/BoardStats.js.map +1 -1
  7. package/lib/commonjs/Squares/components/MySquaresCard.js +11 -1
  8. package/lib/commonjs/Squares/components/MySquaresCard.js.map +1 -1
  9. package/lib/commonjs/Squares/components/MyStatsCard.js +338 -0
  10. package/lib/commonjs/Squares/components/MyStatsCard.js.map +1 -0
  11. package/lib/commonjs/Squares/index.js +26 -3
  12. package/lib/commonjs/Squares/index.js.map +1 -1
  13. package/lib/module/Squares/api/index.js +604 -0
  14. package/lib/module/Squares/api/index.js.map +1 -1
  15. package/lib/module/Squares/components/BidForm.js +0 -1
  16. package/lib/module/Squares/components/BidForm.js.map +1 -1
  17. package/lib/module/Squares/components/BoardStats.js +0 -22
  18. package/lib/module/Squares/components/BoardStats.js.map +1 -1
  19. package/lib/module/Squares/components/MySquaresCard.js +11 -1
  20. package/lib/module/Squares/components/MySquaresCard.js.map +1 -1
  21. package/lib/module/Squares/components/MyStatsCard.js +329 -0
  22. package/lib/module/Squares/components/MyStatsCard.js.map +1 -0
  23. package/lib/module/Squares/index.js +26 -3
  24. package/lib/module/Squares/index.js.map +1 -1
  25. package/lib/typescript/src/Squares/api/index.d.ts +10 -1
  26. package/lib/typescript/src/Squares/api/index.d.ts.map +1 -1
  27. package/lib/typescript/src/Squares/components/BidForm.d.ts.map +1 -1
  28. package/lib/typescript/src/Squares/components/BoardStats.d.ts +1 -2
  29. package/lib/typescript/src/Squares/components/BoardStats.d.ts.map +1 -1
  30. package/lib/typescript/src/Squares/components/MySquaresCard.d.ts +3 -2
  31. package/lib/typescript/src/Squares/components/MySquaresCard.d.ts.map +1 -1
  32. package/lib/typescript/src/Squares/components/MyStatsCard.d.ts +18 -0
  33. package/lib/typescript/src/Squares/components/MyStatsCard.d.ts.map +1 -0
  34. package/lib/typescript/src/Squares/index.d.ts.map +1 -1
  35. package/package.json +1 -1
  36. package/src/Squares/api/index.ts +662 -2
  37. package/src/Squares/components/BidForm.tsx +0 -1
  38. package/src/Squares/components/BoardStats.tsx +3 -11
  39. package/src/Squares/components/MySquaresCard.tsx +9 -2
  40. package/src/Squares/components/MyStatsCard.tsx +167 -0
  41. package/src/Squares/index.tsx +26 -4
  42. package/src/types.d.ts +5 -0
@@ -6,13 +6,12 @@ import type { PlayerSquareProps, SquareProps, SquaresCompetitionProps } from "..
6
6
  import React, { useState } from "react"
7
7
 
8
8
  type BoardStatsProps = {
9
- player_id?:string,
10
9
  squares_competition:SquaresCompetitionProps,
11
10
  squares:SquareProps[],
12
- player_squares:PlayerSquareProps[]
11
+ player_squares:PlayerSquareProps[],
13
12
  }
14
13
 
15
- const BoardStats = ({ player_id, squares_competition, squares, player_squares }:BoardStatsProps) => {
14
+ const BoardStats = ({ squares_competition, squares, player_squares}:BoardStatsProps) => {
16
15
  const [ expanded, setExpanded ] = useState(false);
17
16
 
18
17
  let total_payout = squares_competition.potential_winnings
@@ -20,7 +19,7 @@ const BoardStats = ({ player_id, squares_competition, squares, player_squares }:
20
19
  let iteration_payout = total_payout / squares_competition.payout_frequency
21
20
  let active_ps = player_squares.filter(ps => ps.status == 'active');
22
21
  const ownership_pct = active_ps.length / squares.length * 100
23
- const my_ownership = active_ps.filter(ps => ps.player_id == player_id).length / active_ps.length * 100
22
+
24
23
  return (
25
24
  <View style={{ ...view_styles.section, minWidth:350 }}>
26
25
  <TouchableOpacity style={view_styles.section_header} onPress={() => setExpanded(!expanded)}>
@@ -40,13 +39,6 @@ const BoardStats = ({ player_id, squares_competition, squares, player_squares }:
40
39
  </View>
41
40
  <Text theme="header_2">{(squares.length - active_ps.length).toFixed()} ({(100 - ownership_pct).toFixed(2)}%)</Text>
42
41
  </View>
43
- <View style={{ ...view_styles.body_row, borderBottomWidth:1, borderColor:Colors.shades.shade600 }}>
44
- <View style={{flex:1, marginRight:10}}>
45
- <Text theme="header_2">My Ownership Pct</Text>
46
- <Text style={{ marginTop:3 }} theme="body_2">How much of the total board do I own? (All unbid squares will be extrapolated based on this ownership pct)</Text>
47
- </View>
48
- <Text theme="header_2">{(my_ownership).toFixed()}%</Text>
49
- </View>
50
42
  <View style={{ ...view_styles.body_row, borderBottomWidth:1, borderColor:Colors.shades.shade600 }}>
51
43
  <View style={{flex:1, marginRight:10}}>
52
44
  <Text theme="header_2">Current Total Payout</Text>
@@ -1,5 +1,5 @@
1
1
  import { View, TouchableOpacity, FlatList } from 'react-native';
2
- import type { PlayerSquareProps, SquareOfferProps, SquareProps } from '../../types';
2
+ import type { PlayerSquareProps, SquareOfferProps, SquareProps, SquareValueProps } from '../../types';
3
3
  import { view_styles } from '../../constants/styles';
4
4
  import { Button, Icons, Text } from '../../Components';
5
5
  import React, { useState } from 'react';
@@ -12,22 +12,29 @@ type MySquaresCardProps = {
12
12
  square_offers:SquareOfferProps[],
13
13
  away_abbr?:string,
14
14
  home_abbr?:string,
15
+ my_square_values:SquareValueProps[],
15
16
  comp_status: string,
16
17
  onSquareOffer: (square:SquareProps, action:'add'|'remove') => void
17
18
  }
18
19
 
19
- const MySquaresCard = ({ player_squares, squares, away_abbr, home_abbr, square_offers, comp_status, onSquareOffer }: MySquaresCardProps) => {
20
+ const MySquaresCard = ({ player_squares, squares, away_abbr, home_abbr, square_offers, my_square_values, comp_status, onSquareOffer }: MySquaresCardProps) => {
20
21
  const [ expanded, setExpanded ] = useState(false);
21
22
  const renderPlayerSquares = (data: { item:PlayerSquareProps, index: number }) => {
22
23
  const square = squares.find(s => s.sq_square_id == data.item.sq_square_id);
23
24
  if(!square){ return <></> }
24
25
  const square_offer = square_offers.find(so => so.sq_player_square_id == data.item.sq_player_square_id && so.status == 'offered');
26
+ const square_value = my_square_values.find(sv => sv.sq_square_id == data.item.sq_square_id);
25
27
  return (
26
28
  <View style={{ ...view_styles.body_row, borderBottomWidth:1, borderColor:Colors.shades.shade600 }}>
27
29
  <View style={{ flex:1 }}>
28
30
  <Text theme='header_2'>SQUARE: {home_abbr}: {square.square_score_x}, {away_abbr}: {square.square_score_y}</Text>
29
31
  <Text style={{ marginTop:3 }} theme='body_2'>${data.item.purchase_price.toFixed(2)}</Text>
30
32
  </View>
33
+ {square_value ?
34
+ <View style={{ paddingRight:20, paddingLeft:20 }}>
35
+ <Text size={14} color={square_value.expected_value > 0 ? Colors.utility.success : Colors.utility.error}>${square_value.expected_payout.toFixed(2)}</Text>
36
+ </View>
37
+ :<></>}
31
38
  {comp_status == 'in_progress' ?
32
39
  <View>
33
40
  {square_offer ?
@@ -0,0 +1,167 @@
1
+ import { View, TouchableOpacity, FlatList } from "react-native"
2
+ import { Button, Icons, Text } from "../../Components"
3
+ import { view_styles } from "../../constants/styles"
4
+ import Colors from "../../constants/colors"
5
+ import type { PlayerSquareProps, PublicPlayerProps, SquareProps, SquareResultProps, SquaresCompetitionProps, SquaresExpectedValueProps, SquareValueProps } from "../../types"
6
+ import React, { useState } from "react"
7
+ import moment from "moment-mini"
8
+
9
+ type MyStatsCardProps = {
10
+ player_id?:string,
11
+ squares:SquareProps[],
12
+ home_abbr?:string,
13
+ away_abbr?:string,
14
+ squares_expected_value: SquaresExpectedValueProps
15
+ players:PublicPlayerProps[],
16
+ squares_competition:SquaresCompetitionProps,
17
+ player_squares:PlayerSquareProps[],
18
+ onSquareBid:(square:SquareProps, action:'add'|'remove') => void,
19
+ player_square_history:PlayerSquareProps[],
20
+ square_results: SquareResultProps[]
21
+ }
22
+
23
+ const MyStatsCard = ({ player_id, players, squares_expected_value, away_abbr, home_abbr, squares_competition, player_squares, player_square_history, squares, square_results, onSquareBid}:MyStatsCardProps) => {
24
+ const [ expanded, setExpanded ] = useState(false);
25
+
26
+ const comp_started = moment(squares_competition.begin_datetime).isBefore(moment()) ? true : false
27
+
28
+ let total_payout = squares_competition.potential_winnings
29
+ if(squares_competition.guaranteed_payout && squares_competition.guaranteed_payout > total_payout){ total_payout = squares_competition.guaranteed_payout }
30
+ let active_ps = player_squares.filter(ps => ps.status == 'active');
31
+ const my_ps = active_ps.filter(ps => ps.player_id == player_id)
32
+ let my_outbid_squares = [ ...new Set(player_square_history.filter(psh => psh.status == 'inactive').map(ps => ps.sq_square_id)) ]
33
+ my_outbid_squares = my_outbid_squares.filter(id => !my_ps.map(ps => ps.sq_square_id.toString()).includes(id.toString()))
34
+ const me = players.find(p => p.player_id == player_id);
35
+ console.log(me?.type)
36
+ const my_ownership = my_ps.length / active_ps.length * 100
37
+ const money_in = my_ps.reduce((a,b) => a + b.purchase_price, 0);
38
+ const money_out = square_results.filter(sr => sr.sq_player_square_id && my_ps.map(mp => mp.sq_player_square_id.toString()).includes(sr.sq_player_square_id.toString())).reduce((a,b) => a + b.winnings, 0)
39
+ const earnings = money_out - money_in
40
+ let roi = 0
41
+ if(money_in > 0){
42
+ roi = earnings / money_in
43
+ }
44
+
45
+ const suggested_squares = squares_expected_value.other_square_values.filter(sv => sv.after_purchase_expected_value > 0).sort((a,b) => b.after_purchase_expected_value - a.after_purchase_expected_value).slice(0, 3)
46
+
47
+ const renderSuggestions = (data: { item:SquareValueProps, index:number }) => {
48
+ const square = squares.find(s => s.sq_square_id == data.item.sq_square_id);
49
+ if(!square){ return <></> }
50
+
51
+ return (
52
+ <View style={{ backgroundColor:Colors.shades.white, borderRadius:8, width:110, margin:3, ...view_styles.float }}>
53
+ <View style={{ flexDirection:'row', alignItems:'center', padding:5, borderBottomWidth:1, borderBottomColor:Colors.shades.shade600, borderTopRightRadius:8, borderTopLeftRadius:8 }}>
54
+ <View style={{flex:1}}>
55
+ <Icons.ChevronIcon direction="up" color={Colors.utility.success} size={8} />
56
+ </View>
57
+ <Text color={Colors.utility.success} weight='bold' size={14}>EV ${data.item.after_purchase_expected_payout.toFixed(2)}</Text>
58
+ </View>
59
+ <View style={{ padding:10, justifyContent:'center' }}>
60
+ <View style={{ flexDirection:'row', alignItems:'center' }}>
61
+ <Text style={{ flex:1 }} theme='body'>{home_abbr}</Text>
62
+ <Text theme='header_2'>{square.square_score_x}</Text>
63
+ </View>
64
+ <View style={{ flexDirection:'row', alignItems:'center' }}>
65
+ <Text style={{ flex:1 }} theme='body'>{away_abbr}</Text>
66
+ <Text theme='header_2'>{square.square_score_y}</Text>
67
+ </View>
68
+ </View>
69
+ <View style={{ padding:5 }}>
70
+ <Button
71
+ title={`$${data.item.next_purchase_price}`}
72
+ title_color={Colors.shades.white}
73
+ backgroundColor={Colors.brand.electric}
74
+ onPress={() => onSquareBid(square, 'add')}
75
+ />
76
+ </View>
77
+ </View>
78
+ )
79
+ }
80
+
81
+
82
+ let ev_pct = 0
83
+ if(!isNaN(squares_expected_value.ev_pct)){ ev_pct = squares_expected_value.ev_pct }
84
+
85
+ return (
86
+ <View style={{ ...view_styles.section, minWidth:350 }}>
87
+ <TouchableOpacity style={view_styles.section_header} onPress={() => setExpanded(!expanded)}>
88
+ <View style={{ justifyContent:'center', alignItems:'center' }}>
89
+ <Text size={14} color={squares_expected_value.expected_value > 0 ? Colors.utility.success: Colors.utility.error} weight='bold'>{(ev_pct * 100).toFixed(2)}%</Text>
90
+ <Text style={{ marginTop:3 }} size={12} color={Colors.brand.midnight} weight='regular'>EV</Text>
91
+ </View>
92
+ <View style={{ flex:1, marginLeft:10 }}>
93
+ <Text theme="header">MY STATS (BETA)</Text>
94
+ <Text style={{ marginTop: 4 }} theme="body_2">Current statistics from the squares board</Text>
95
+ </View>
96
+ <Icons.ChevronIcon direction={expanded ? 'up' : 'down'} color={Colors.brand.midnight} size={8} />
97
+ </TouchableOpacity>
98
+ {expanded && !comp_started ?
99
+ <View style={{ padding:5, backgroundColor:Colors.incentive.gold_faded}}>
100
+ <View style={{ padding:5 }}>
101
+ <Text theme="header">Suggested Squares</Text>
102
+ <Text style={{ marginTop:3 }} theme="body_2">Suggestion are determined by running thousands of simulations based on the board in its current state. These will change frequently as the board changes.</Text>
103
+ </View>
104
+ <View style={{ marginTop:3, padding:10, justifyContent:'center', alignItems:'center' }}>
105
+ <FlatList
106
+ data={suggested_squares}
107
+ horizontal
108
+ renderItem={renderSuggestions}
109
+ keyExtractor={(item) => item.sq_square_id.toString()}
110
+ />
111
+ </View>
112
+ </View>
113
+ :<></>}
114
+ {expanded ?
115
+ <View style={view_styles.section_body}>
116
+ <View style={{ ...view_styles.body_row, borderBottomWidth:1, borderColor:Colors.shades.shade600 }}>
117
+ <View style={{flex:1, marginRight:10}}>
118
+ <Text theme="header_2">Expected Value (pct)</Text>
119
+ <Text style={{ marginTop:3 }} theme="body_2">Based on your owned squares and ownership pct (for extrapolation), we can calculate the probable earnings of your squares over thousands of simulations</Text>
120
+ </View>
121
+ <View style={{ justifyContent:'center', alignItems:'center' }}>
122
+ <Text color={squares_expected_value.expected_value > 0 ? Colors.utility.success: Colors.utility.error} weight='bold' size={14}>${squares_expected_value.expected_value.toFixed(2)}</Text>
123
+ <Text style={{ marginTop:3 }} color={squares_expected_value.expected_value > 0 ? Colors.utility.success: Colors.utility.error} weight='regular' size={14}>({(ev_pct * 100).toFixed(2)}%)</Text>
124
+ </View>
125
+ </View>
126
+ <View style={{ ...view_styles.body_row, borderBottomWidth:1, borderColor:Colors.shades.shade600 }}>
127
+ <View style={{flex:1, marginRight:10}}>
128
+ <Text theme="header_2">Outbid Squares</Text>
129
+ <Text style={{ marginTop:3 }} theme="body_2">Number of squares you bid on but were outbid or sold</Text>
130
+ </View>
131
+ <Text theme="header_2">{my_outbid_squares.length} Squares</Text>
132
+ </View>
133
+ <View style={{ ...view_styles.body_row, borderBottomWidth:1, borderColor:Colors.shades.shade600 }}>
134
+ <View style={{flex:1, marginRight:10}}>
135
+ <Text theme="header_2">My Ownership (Pct)</Text>
136
+ <Text style={{ marginTop:3 }} theme="body_2">How much of the total board do I own? (All unbid squares will be extrapolated based on this ownership pct)</Text>
137
+ </View>
138
+ <Text theme="header_2">{my_ps.length} Squares ({(my_ownership).toFixed()}%)</Text>
139
+ </View>
140
+ <View style={{ ...view_styles.body_row, borderBottomWidth:1, borderColor:Colors.shades.shade600 }}>
141
+ <View style={{flex:1, marginRight:10}}>
142
+ <Text theme="header_2">My Total Paid</Text>
143
+ <Text style={{ marginTop:3 }} theme="body_2">How much have I paid for my ownership pct</Text>
144
+ </View>
145
+ <Text theme="header_2">${(money_in).toFixed(2)} ({((money_in / total_payout)*100).toFixed(2)}%)</Text>
146
+ </View>
147
+ <View style={{ ...view_styles.body_row, borderBottomWidth:1, borderColor:Colors.shades.shade600 }}>
148
+ <View style={{flex:1, marginRight:10}}>
149
+ <Text theme="header_2">Winnings Received</Text>
150
+ <Text style={{ marginTop:3 }} theme="body_2">How much have I received from winning or selling squares</Text>
151
+ </View>
152
+ <Text theme="header_2">${(money_out).toFixed(2)}</Text>
153
+ </View>
154
+ <View style={{ ...view_styles.body_row, borderBottomWidth:1, borderColor:Colors.shades.shade600 }}>
155
+ <View style={{flex:1, marginRight:10}}>
156
+ <Text theme="header_2">ROI</Text>
157
+ <Text style={{ marginTop:3 }} theme="body_2">What is my current return on investment (earnings / total paid)</Text>
158
+ </View>
159
+ <Text color={roi > 0 ? Colors.utility.success : Colors.utility.error} weight='bold' size={14}>{(roi * 100).toFixed(2)}%</Text>
160
+ </View>
161
+ </View>
162
+ :<></>}
163
+ </View>
164
+ )
165
+ }
166
+
167
+ export default MyStatsCard
@@ -16,6 +16,7 @@ import type { BEEventProps } from "../Observer/api/types";
16
16
  import OfferForm from "./components/OfferForm";
17
17
  import MySquaresCard from "./components/MySquaresCard";
18
18
  import { view_styles } from "../constants/styles";
19
+ import MyStatsCard from "./components/MyStatsCard";
19
20
 
20
21
  type SquaresModuleProps = {
21
22
  player_id?:string,
@@ -68,11 +69,12 @@ const SquaresModule = ({ sq_comp_id, player_id, distinct_id, onRequestAuthentica
68
69
  const { square_bids, draft_square_offers, submit_ready } = board_data;
69
70
  const { loading, league, event, players, loaded, squares_competition, squares, squares_type, squares_payout_type, square_results, square_offers, player_square_history, player_squares } = module_data;
70
71
 
72
+ const squares_expected_value = SqauresHelpers.getMyExpectedValue(squares, player_squares.filter(ps => ps.status == 'active' && ps.player_id == player_id), squares_competition, player_id)
71
73
 
72
74
  const my_squares = player_squares.filter(ps => ps.status == 'active' && ps.player_id == player_id);
73
75
  const home_abbr = event?.home?.abbr??squares_competition?.event_backup?.home?.abbr
74
76
  const away_abbr = event?.away?.abbr??squares_competition?.event_backup?.away?.abbr
75
-
77
+ const joined = SqauresHelpers.amIParticipating(player_squares, player_square_history, player_id);
76
78
 
77
79
  useEffect(() => {
78
80
  if(!sq_comp_id){ return }
@@ -85,7 +87,9 @@ const SquaresModule = ({ sq_comp_id, player_id, distinct_id, onRequestAuthentica
85
87
  const d = await SquaresApi.getSquareCompetitionById(sq_comp_id);
86
88
  const evs = await SquaresApi.getEventsByEventIds([d.squares_competition.event_id]);
87
89
  const league_id = evs[0]?.league_id
88
- let ps = await SquaresApi.getPlayersByPlayerIds([ ...new Set(d.player_squares.map(ps => ps.player_id)) ])
90
+ let unique_player_ids = [ ...new Set(d.player_squares.map(ps => ps.player_id)) ]
91
+ if(player_id){ unique_player_ids.push(player_id) }
92
+ let ps = await SquaresApi.getPlayersByPlayerIds(unique_player_ids)
89
93
  let l:LeagueProps | undefined = undefined
90
94
  if(league_id){
91
95
  l = await SquaresApi.getLeagueById(league_id);
@@ -125,6 +129,7 @@ const SquaresModule = ({ sq_comp_id, player_id, distinct_id, onRequestAuthentica
125
129
  const resp = await SquaresApi.buySquares(squares_competition.sq_comp_id, square_bids)
126
130
  if(needs_reload){ handleUpdateBoardFromBuy(resp) } //If we somehow got disconnected from the socket, we need to load it
127
131
  setBoardData({ ...board_data, square_bids:[], submit_ready:{ is_loading: false, is_ready: false } })
132
+ setBidFormExpanded(false);
128
133
  }
129
134
 
130
135
  const handleSubmitOffer = async() => {
@@ -280,12 +285,28 @@ const SquaresModule = ({ sq_comp_id, player_id, distinct_id, onRequestAuthentica
280
285
  />
281
286
  :<></>}
282
287
  <BoardStats
283
- player_id={player_id}
284
288
  squares_competition={squares_competition}
285
289
  squares={squares}
286
290
  player_squares={player_squares}
287
291
  />
288
-
292
+ {joined ?
293
+ <MyStatsCard
294
+ player_id={player_id}
295
+ players={players}
296
+ home_abbr={home_abbr}
297
+ squares_expected_value={squares_expected_value}
298
+ away_abbr={away_abbr}
299
+ onSquareBid={(square, action) => {
300
+ handleSquareBid(square, action)
301
+ setBidFormExpanded(true);
302
+ }}
303
+ squares={squares}
304
+ player_square_history={player_square_history}
305
+ player_squares={player_squares}
306
+ square_results={square_results}
307
+ squares_competition={squares_competition}
308
+ />
309
+ :<></>}
289
310
  {square_results.length > 0 ?
290
311
  <ResultsCard
291
312
  home_abbr={home_abbr}
@@ -329,6 +350,7 @@ const SquaresModule = ({ sq_comp_id, player_id, distinct_id, onRequestAuthentica
329
350
  squares={squares}
330
351
  square_offers={square_offers}
331
352
  away_abbr={away_abbr}
353
+ my_square_values={squares_expected_value.my_square_values}
332
354
  home_abbr={home_abbr}
333
355
  comp_status={comp_status}
334
356
  onSquareOffer={handleSquareOffer}
package/src/types.d.ts CHANGED
@@ -1458,6 +1458,9 @@ export interface SquaresCompetitionProps {
1458
1458
  auth_strategy_id?:string
1459
1459
  }
1460
1460
 
1461
+ export interface SquaresExpectedValueProps {
1462
+ ev_pct:number, money_in:number, expected_payout:number, expected_value:number, other_square_values:SquareValueProps[], my_square_values:SquareValueProps[]
1463
+ }
1461
1464
 
1462
1465
  export interface SquaresTypeProps {
1463
1466
  sq_type_id:string, sq_type_name:string, sq_type_description:string, empty_square_action:string,
@@ -1475,6 +1478,8 @@ export interface SquareProps {
1475
1478
  create_datetime:any, last_update_datetime:any
1476
1479
  }
1477
1480
 
1481
+ export interface SquareValueProps { sq_square_id:string, probability:number, expected_value: number, expected_payout:number, next_purchase_price:number, after_purchase_expected_payout:number, after_purchase_expected_value:number }
1482
+
1478
1483
  export interface OfferResponseProps { squares_competition?:SquaresCompetitionProps, updated_offers:SquareOfferProps[], saved_player_squares:PlayerSquareProps[], removed_player_squares:PlayerSquareProps[] }
1479
1484
  export interface BuySquaresResponseProps { squares_competition:SquaresCompetitionProps, saved_player_squares:PlayerSquareProps[], removed_player_squares:PlayerSquareProps[], updated_squares:SquareProps[] }
1480
1485