diff --git a/Server/src/public/index.html b/Server/src/public/index.html
new file mode 100644
index 0000000..f61f400
--- /dev/null
+++ b/Server/src/public/index.html
@@ -0,0 +1,125 @@
+
+
+
+
+
+ Bets and Odds
+
+
+
+ Betting System
+
+
+ Current Odds
+
+
+ Betting Graph
+
+
+ Odds on Offer
+
+
+
+ All Bets
+
+
+
+
+
diff --git a/Server/src/server.ts b/Server/src/server.ts
index 9ec4556..cee5fa7 100644
--- a/Server/src/server.ts
+++ b/Server/src/server.ts
@@ -1,134 +1,138 @@
import express from 'express'
+import path from 'path'
const app = express()
const port = 3000
const fee = 0.05 // 0.01 = 1%
+const initialLiquidity = 1000 // Initial liquidity for the market
-function countLiquidity (sharesHeld: number[]): number {
- return sharesHeld.reduce((acc, val) => acc + val, 0)
+interface UserBalances { [key: number]: number }
+interface TeamFunds { [team: number]: number }
+interface Bet {
+ userId: number
+ team: number
+ amount: number
+ odds: number[]
}
-function calculateOdds (sharesHeld: number[]): number[] {
- const liquidity = countLiquidity(sharesHeld)
- const exps = sharesHeld.map(shares => Math.exp(shares / liquidity))
+const userBalances: UserBalances = { 1: 1000, 2: 1000, 3: 1000, 4: 1000 }
+let teamFunds: TeamFunds = { 0: initialLiquidity, 1: initialLiquidity } // Initial funds for each team
+const bets: Bet[] = []
+
+function calculateTotalFunds (funds: TeamFunds): number {
+ return Object.values(funds).reduce((acc: number, val: number) => acc + val, 0)
+}
+
+function calculateOdds (funds: TeamFunds): number[] {
+ const totalFunds = calculateTotalFunds(funds)
+ const exps = Object.values(funds).map(fund => Math.exp(fund / totalFunds))
return exps
}
-// function calculateMarginalPrice (team: number, sharesHeld: number[]): number {
-// const liquidity = countLiquidity(sharesHeld)
-// console.log('Liquidity:', sharesHeld)
-// const exps = sharesHeld.map(shares => Math.exp(shares / liquidity))
-// console.log('Exps:', exps)
-// const sumExp = exps.reduce((acc, val) => acc + val, 0)
-// return exps[team] / sumExp
-// }
-
-function countBets (userShares: UserShare[]): number[] {
- return Object.values(userShares.reduce((acc, curr) => {
- const index = Object.keys(acc).length
- acc[index] = Object.values(curr).reduce((a: number, b: number) => a + b, 0)
- return acc
- }, {}))
-}
-
-function calculateCost (sharesHeld: number[]): number {
- const liquidity = countLiquidity(sharesHeld)
- const exps = sharesHeld.map(shares => Math.exp(shares / liquidity))
- const sumExp = exps.reduce((acc, val) => acc + val, 0)
+function calculateCost (funds: TeamFunds): number {
+ const totalFunds = calculateTotalFunds(funds)
+ const exps = Object.values(funds).map(fund => Math.exp(fund / totalFunds))
+ const sumExp = exps.reduce((acc: number, val: number) => acc + val, 0)
const lnSumExp = Math.log(sumExp)
- const result = liquidity * lnSumExp
+ const result = totalFunds * lnSumExp
if (Number.isNaN(result)) return 0
return result
}
-function placeBet (userShares: UserShare[], userId: number, team: number, sharesBought: number): UserShare[] {
- const initialCost = calculateCost(countBets(userShares))
+function placeBet (userBalances: UserBalances, funds: TeamFunds, userId: number, team: number, cashAmount: number): TeamFunds {
+ const initialCost = calculateCost(funds)
- if (sharesBought === undefined || sharesBought === null || sharesBought <= 0) {
- console.log('No shares bought')
- return userShares
+ if (cashAmount === undefined || cashAmount === null || cashAmount <= 0) {
+ console.log('No cash amount specified')
+ return funds
}
- sharesBought *= 1 - fee
+ cashAmount *= 1 - fee
- if (team === undefined || userShares[team] === undefined) {
+ if (team === undefined || funds[team] === undefined) {
console.log('Invalid team')
- return userShares
+ return funds
}
- const newUserShares = userShares
-
- if (newUserShares[team][userId] === undefined) newUserShares[team][userId] = 0
- newUserShares[team][userId] += sharesBought
-
- const transactionCost = calculateCost(countBets(userShares)) - initialCost
-
- if (transactionCost > userBalances[userId] && userBalances[userId] !== undefined && userBalances[userId] !== null) {
+ if (userBalances[userId] < cashAmount) {
console.log('Not enough balance')
- return userShares
+ return funds
+ }
+
+ const newFunds = { ...funds }
+ newFunds[team] += cashAmount
+
+ const transactionCost = calculateCost(newFunds) - initialCost
+
+ if (transactionCost > userBalances[userId]) {
+ console.log('Not enough balance after transaction')
+ return funds
}
userBalances[userId] -= transactionCost
- if (dollarsBet[userId] === undefined) dollarsBet[userId] = 0
- dollarsBet[userId] += transactionCost
- console.log('Paid $' + (transactionCost as unknown as string) + ' for ' + (sharesBought as unknown as string) + ' shares on team ' + (team as unknown as string) + ' by user ' + (userId as unknown as string))
+ // Record the bet with the current odds
+ const odds = calculateOdds(newFunds)
+ bets.push({ userId, team, amount: cashAmount, odds })
- return newUserShares
+ return newFunds
}
-interface UserShare { [key: number]: number }
+function probabilityToDecimalOdds (probability: number): string {
+ return (1 / probability).toFixed(2)
+}
-const userBalances: UserShare = { 1: 1000, 2: 1000, 3: 1000, 4: 1000 }
-const dollarsBet: UserShare = { 0: 2 }
-let userShares: UserShare[] = [{ 0: 1 }, { 0: 1 }]
-
-// app.get('/bets', (_, res) => {
-// const bets = countBets(userShares)
-// const odds = bets.map((_, i) => {
-// return calculateMarginalPrice(i, bets).toFixed(4)
-// })
-
-// res.send(JSON.stringify({
-// bets,
-// odds
-// }))
-// })
+app.use(express.static(path.join(__dirname, 'public')))
app.get('/bets', (req, res) => {
- res.header('Content-Type', 'application/json')
- const userId: number = parseInt(req.query.userId as unknown as string)
- const team: number = parseInt(req.query.team as unknown as string)
- const sharesBought: number = parseInt(req.query.sharesBought as unknown as string)
+ const userId: number = parseInt(req.query.userId as string)
+ const team: number = parseInt(req.query.team as string)
+ const cashAmount: number = parseInt(req.query.cashAmount as string)
- if (sharesBought === undefined || sharesBought === null || sharesBought <= 0) {
- res.send('No shares bought')
+ if (cashAmount === undefined || cashAmount === null || cashAmount <= 0) {
+ res.send('No cash amount specified')
+ return
}
- if (team === undefined || userShares[team] === undefined) {
+ if (team === undefined || teamFunds[team] === undefined) {
res.send('Invalid team')
return
}
- userShares = placeBet(userShares, userId, team, sharesBought)
+ teamFunds = placeBet(userBalances, teamFunds, userId, team, cashAmount)
- const bets = countBets(userShares)
- const odds: number[] = calculateOdds(bets)
+ const odds: string[] = Object.keys(teamFunds).map(teamKey => {
+ const teamIndex = parseInt(teamKey)
+ return probabilityToDecimalOdds(calculateOdds(teamFunds)[teamIndex])
+ })
- const liquidity = countLiquidity(bets)
+ const totalFunds = calculateTotalFunds(teamFunds)
res.send(JSON.stringify({
- bets,
odds,
- yourBets: userShares.map((shares, team) => {
- const userBets = shares[userId] ?? 0
- return {
- shares: userBets,
- winPayout: liquidity * Math.floor(100 * (userBets / bets[team])) / 100,
- dollarsBet: dollarsBet[userId] ?? 0
- }
- })
+ yourBets: bets.filter(bet => bet.userId === userId),
+ allBets: bets,
+ totalFunds
+ }))
+})
+
+app.get('/odds-on-offer', (req, res) => {
+ const cashAmount: number = parseInt(req.query.cashAmount as string)
+
+ if (cashAmount === undefined || cashAmount === null || cashAmount <= 0) {
+ res.send('No cash amount specified')
+ return
+ }
+
+ const newFunds = { ...teamFunds, 0: teamFunds[0] + cashAmount, 1: teamFunds[1] }
+ const oddsOnOffer = Object.keys(newFunds).map(teamKey => {
+ const teamIndex = parseInt(teamKey)
+ return probabilityToDecimalOdds(calculateOdds(newFunds)[teamIndex])
+ })
+
+ res.send(JSON.stringify({
+ oddsOnOffer
}))
})