wip: case opening

This commit is contained in:
Milo
2025-12-16 17:14:07 +01:00
parent 073aaafe67
commit d84f55daa0
4 changed files with 122 additions and 33 deletions

View File

@@ -603,9 +603,9 @@ export const getAllAkhys = flopoDB.prepare(
----------------------------*/
export const insertSkin = flopoDB.prepare(
`INSERT INTO skins (uuid, displayName, contentTierUuid, displayIcon, user_id, tierRank, tierColor, tierText,
basePrice, currentLvl, currentChroma, currentPrice, maxPrice)
basePrice, maxPrice)
VALUES (@uuid, @displayName, @contentTierUuid, @displayIcon, @user_id, @tierRank, @tierColor, @tierText,
@basePrice, @currentLvl, @currentChroma, @currentPrice, @maxPrice)`,
@basePrice, @maxPrice)`,
);
export const updateSkin = flopoDB.prepare(
`UPDATE skins

View File

@@ -9,6 +9,7 @@ import {
getMarketOffersBySkin,
getOfferBids,
getSkin,
getAllAvailableSkins,
getUser,
getUserElo,
getUserGames,
@@ -116,14 +117,60 @@ export function apiRoutes(client, io) {
router.get("/carousel-skins", (req, res) => {
try {
const dbSkins = getAllAvailableSkins.all();
const filteredSkins = skins.filter(
(s) => s.displayIcon !== null && s.displayName.toLowerCase().includes("champions"),
(s) => dbSkins.find((dbSkin) => dbSkin.uuid === s.uuid),
);
filteredSkins.forEach((s) => {
let dbSKin = getSkin.get(s.uuid);
s.tierColor = dbSKin?.tierColor;
let dbSkin = getSkin.get(s.uuid);
s.tierColor = dbSkin?.tierColor;
});
res.json(filteredSkins);
const tierWeights = {
"12683d76-48d7-84a3-4e09-6985794f0445": 50, // Select
"0cebb8be-46d7-c12a-d306-e9907bfc5a25": 30, // Deluxe
"60bca009-4182-7998-dee7-b8a2558dc369": 15, // Premium
"e046854e-406c-37f4-6607-19a9ba8426fc": 4, // Exclusive
"411e4a55-4e59-7757-41f0-86a53f101bb5": 1, // Ultra
}
filteredSkins.forEach((s) => {
s.weight = tierWeights[s.tierUuid] ?? 1; // fallback if missing
});
function weightedSample(arr, count) {
let totalWeight = arr.reduce((sum, x) => sum + x.weight, 0);
const list = [...arr];
const result = [];
for (let i = 0; i < count && list.length > 0; i++) {
let r = Math.random() * totalWeight;
let running = 0;
let pickIndex = -1;
for (let j = 0; j < list.length; j++) {
running += list[j].weight;
if (r <= running) {
pickIndex = j;
break;
}
}
if (pickIndex < 0) break;
const picked = list.splice(pickIndex, 1)[0];
result.push(picked);
// Subtract removed weight
totalWeight -= picked.weight;
}
return result;
}
const selectedSkins = weightedSample(filteredSkins, 100);
const randomSelectedSkinIndex = Math.floor(Math.random() * selectedSkins.length);
const randomSelectedSkinUuid = selectedSkins[randomSelectedSkinIndex].uuid;
res.json({ selectedSkins, randomSelectedSkinUuid, randomSelectedSkinIndex });
} catch (error) {
console.error("Error fetching skins:", error);
res.status(500).json({ error: "Failed to fetch skins." });

View File

@@ -13,6 +13,7 @@ import {
getUser,
insertBid,
insertLog,
insertMarketOffer,
updateUserCoins,
} from "../../database/index.js";
import { emitMarketUpdate } from "../socket.js";
@@ -68,12 +69,35 @@ export function marketRoutes(client, io) {
});
router.post("/place-offer", async (req, res) => {
const { seller_id, skin_uuid, starting_price, delay, duration, timestamp } = req.body;
const now = Date.now();
try {
const skin = getSkin.get(skin_uuid);
if (!skin) return res.status(404).send({ error: "Skin not found" });
const seller = getUser.get(seller_id);
if (!seller) return res.status(404).send({ error: "Seller not found" });
if (skin.user_id !== seller.id) return res.status(403).send({ error: "You do not own this skin" });
const opening_at = now + delay;
const closing_at = opening_at + duration;
insertMarketOffer.run({
id: Date.now() + '-' + seller.id + '-' + skin.uuid,
skin_uuid: skin.uuid,
seller_id: seller.id,
starting_price: starting_price,
buyout_price: null,
status: delay > 0 ? "pending" : "open",
opening_at: opening_at,
closing_at: closing_at,
});
// Placeholder for placing an offer logic
// Extract data from req.body and process accordingly
res.status(200).send({ message: "Offer placed successfully" });
await emitMarketUpdate();
res.status(200).send({ message: "Offre créée avec succès" });
} catch (e) {
res.status(500).send({ error: e });
console.log(e)
return res.status(500).send({ error: e });
}
});

View File

@@ -21,6 +21,7 @@ import {
updateUserCoins,
} from "../database/index.js";
import { activeInventories, activePredis, activeSearchs, pokerRooms, skins } from "../game/state.js";
import { emitMarketUpdate } from "../server/socket.js";
export async function InstallGlobalCommands(appId, commands) {
// API endpoint to overwrite global commands
@@ -119,7 +120,7 @@ export async function getAkhys(client) {
*/
export function setupCronJobs(client, io) {
// Every 5 minutes: Update market offers
cron.schedule("*/1 * * * *", () => {
cron.schedule("* * * * *", () => {
console.log("[Cron] Checking market offers for updates...");
handleMarketOffersUpdate();
});
@@ -258,38 +259,55 @@ export async function postAPOBuy(userId, amount) {
function handleMarketOffersUpdate() {
const now = Date.now();
const offers = getMarketOffers.all();
offers.forEach((offer) => {
console.log(`[Market Cron] Checking offer ID: ${offer.id}, Status: ${offer.status}`);
offers.forEach(async (offer) => {
if (now >= offer.opening_at && offer.status === "pending") {
updateMarketOffer.run({ id: offer.id, final_price: null, buyer_id: null, status: "open" });
//TODO: Maybe notify seller that their offer is now open
await emitMarketUpdate();
}
if (now >= offer.closing_at && offer.status !== "closed") {
const bids = getOfferBids.all(offer.id);
const lastBid = bids[0];
const seller = getUser.get(offer.seller_id);
const buyer = getUser.get(lastBid.bidder_id);
try {
// Change skin ownership
const skin = getSkin.get(offer.skin_uuid);
if (!skin) throw new Error(`Skin not found for offer ID: ${offer.id}`);
updateSkin.run({
user_id: buyer.id,
currentLvl: skin.currentLvl,
currentChroma: skin.currentChroma,
currentPrice: skin.currentPrice,
uuid: skin.uuid,
});
if (bids.length === 0) {
// No bids placed, mark as closed without a sale
updateMarketOffer.run({
id: offer.id,
buyer_id: buyer.id,
final_price: lastBid.offer_amount,
buyer_id: null,
final_price: null,
status: "closed",
});
const newUserCoins = seller.coins + lastBid.offer_amount;
updateUserCoins.run({ id: seller.id, coins: newUserCoins });
//TODO: Notify users in DMs
} catch (e) {
console.error(`[Market Cron] Error processing offer ID: ${offer.id}`, e);
await emitMarketUpdate();
} else {
const lastBid = bids[0];
const seller = getUser.get(offer.seller_id);
const buyer = getUser.get(lastBid.bidder_id);
try {
// Change skin ownership
const skin = getSkin.get(offer.skin_uuid);
if (!skin) throw new Error(`Skin not found for offer ID: ${offer.id}`);
updateSkin.run({
user_id: buyer.id,
currentLvl: skin.currentLvl,
currentChroma: skin.currentChroma,
currentPrice: skin.currentPrice,
uuid: skin.uuid,
});
updateMarketOffer.run({
id: offer.id,
buyer_id: buyer.id,
final_price: lastBid.offer_amount,
status: "closed",
});
const newUserCoins = seller.coins + lastBid.offer_amount;
updateUserCoins.run({ id: seller.id, coins: newUserCoins });
//TODO: Notify users in DMs
await emitMarketUpdate();
} catch (e) {
console.error(`[Market Cron] Error processing offer ID: ${offer.id}`, e);
}
}
}
});
}