feat: add factory sample machines and robot pricing conversations

This commit is contained in:
2026-10-28 12:53:07 +03:30
parent d0da416923
commit 55d4123fe5
71 changed files with 8179 additions and 3978 deletions
+91 -25
View File
@@ -1,26 +1,50 @@
// Robot Market machines in the playable Park Mellat area. Positions are path points taken from
// the OpenStreetMap data (local metres, see geo.js); the machine is placed beside that path.
export const CATEGORIES = {
factory: { label: 'کارخانه', icon: '🏭' },
park: { label: 'پارک', icon: '🌳' },
university: { label: 'دانشگاه', icon: '🎓' },
school: { label: 'مدرسه', icon: '🏫' },
metro: { label: 'ایستگاه مترو', icon: 'Ⓜ' },
mall: { label: 'مرکز خرید', icon: '🛍' },
test: { label: 'نقطهٔ آزمایشی GPS', icon: '🧪' },
factory: {
label: 'کارخانه',
icon: '🏭',
},
park: {
label: 'پارک',
icon: '🌳',
},
university: {
label: 'دانشگاه',
icon: '🎓',
},
school: {
label: 'مدرسه',
icon: '🏫',
},
metro: {
label: 'ایستگاه مترو',
icon: 'Ⓜ',
},
mall: {
label: 'مرکز خرید',
icon: '🛍',
},
test: {
label: 'نقطهٔ آزمایشی GPS',
icon: '🧪',
},
};
const ALL_DAY = [7 * 60, 23 * 60];
export const FACTORY = {
name: 'شرکت روبات مارکت',
tagline: 'سازندهٔ دستگاه‌های وندینگ هوشمند',
address: 'بزرگراه مشهد–چناران، خیابان کاله، کنار پارک علم و فناوری خراسان',
// Centre of the compound and the direction of its driveway (towards the gate on Kaleh Street).
center: { x: -10308.4, z: -14964.2 },
axis: { x: Math.SQRT1_2, z: Math.SQRT1_2 },
center: {
x: -10308.4,
z: -14964.2,
},
axis: {
x: Math.SQRT1_2,
z: Math.SQRT1_2,
},
};
export const machines = [
{
id: 'factory',
@@ -38,7 +62,10 @@ export const machines = [
name: 'بوستان ملت',
category: 'park',
address: 'بزرگراه وکیل‌آباد، ورودی جنوبی بوستان ملت، نزدیک ایستگاه مترو پارک ملت',
anchor: { x: -487.6, z: -326.4 },
anchor: {
x: -487.6,
z: -326.4,
},
hours: ALL_DAY,
priceFactor: 1,
products: ['water', 'juice', 'lemonade', 'tea', 'biscuit', 'chocolate', 'cake', 'nuts'],
@@ -49,7 +76,10 @@ export const machines = [
name: 'مجموعه آموزشی راحیل',
category: 'school',
address: 'بولوار امامت، کوچهٔ امامت ۲، کنار در ورودی مدرسه',
anchor: { x: -554.6, z: -569.7 },
anchor: {
x: -554.6,
z: -569.7,
},
hours: [7 * 60 + 30, 13 * 60 + 30],
priceFactor: 0.9,
products: ['water', 'milk', 'juice', 'biscuit', 'cake'],
@@ -60,7 +90,10 @@ export const machines = [
name: 'دانشگاه فردوسی مشهد',
category: 'university',
address: 'میدان آزادی، پردیس دانشگاه فردوسی، مسیر پیاده‌روی مرکزی',
anchor: { x: -936, z: 645 },
anchor: {
x: -936,
z: 645,
},
hours: ALL_DAY,
priceFactor: 0.8,
products: ['water', 'tea', 'milk', 'biscuit', 'chocolate', 'nuts', 'cake'],
@@ -71,7 +104,10 @@ export const machines = [
name: 'دانشکدهٔ ادبیات دکتر شریعتی',
category: 'university',
address: 'پردیس دانشگاه فردوسی، بولوار دانش، جلوی دانشکدهٔ ادبیات',
anchor: { x: -417.1, z: 966.3 },
anchor: {
x: -417.1,
z: 966.3,
},
hours: ALL_DAY,
priceFactor: 0.8,
products: ['water', 'tea', 'lemonade', 'biscuit', 'chocolate'],
@@ -82,7 +118,10 @@ export const machines = [
name: 'دانشگاه علوم پزشکی مشهد',
category: 'university',
address: 'میدان آزادی، پردیس دانشگاه علوم پزشکی مشهد',
anchor: { x: -272.1, z: 150.6 },
anchor: {
x: -272.1,
z: 150.6,
},
hours: ALL_DAY,
priceFactor: 0.8,
products: ['water', 'juice', 'milk', 'nuts', 'biscuit'],
@@ -93,7 +132,10 @@ export const machines = [
name: 'ایستگاه مترو آزادی',
category: 'metro',
address: 'بولوار ملک‌آباد، ورودی ایستگاه مترو آزادی',
anchor: { x: 494.1, z: 280.3 },
anchor: {
x: 494.1,
z: 280.3,
},
hours: [6 * 60, 22 * 60],
priceFactor: 1,
products: ['water', 'tea', 'juice', 'chocolate', 'biscuit'],
@@ -104,7 +146,10 @@ export const machines = [
name: 'مشهد مال',
category: 'mall',
address: 'خیابان اخوان ثالث، کنار ورودی پارکینگ مشهد مال',
anchor: { x: 1940.6, z: -367.8 },
anchor: {
x: 1940.6,
z: -367.8,
},
hours: [10 * 60, 23 * 60],
priceFactor: 1.1,
products: ['water', 'juice', 'milk', 'tea', 'lemonade', 'chocolate', 'cake', 'nuts', 'biscuit'],
@@ -114,6 +159,13 @@ export const machines = [
// GPS test points at real coordinates beside the factory, for checking real-world mode on a phone.
// They exist only while real-world mode is on; `spot` is where the player stands to buy.
/**
* Runs the test point operation for this subsystem.
* @param {*} n - n.
* @param {*} lat - lat.
* @param {*} lon - lon.
* @returns {*} Operation result, when applicable.
*/
const testPoint = (n, lat, lon) => ({
id: `test-${n}`,
name: `نقطهٔ آزمایشی ${['۱', '۲', '۳'][n - 1]}`,
@@ -121,7 +173,10 @@ const testPoint = (n, lat, lon) => ({
test: true,
address: `کنار کارخانهٔ روبات مارکت · ${lat.toFixed(6)}, ${lon.toFixed(6)}`,
anchor: null,
spot: { lat, lon },
spot: {
lat,
lon,
},
hours: [0, 24 * 60],
priceFactor: 0.5,
products: ['water', 'biscuit'],
@@ -135,11 +190,22 @@ machines.push(
// Shown on the map as the next area to unlock.
export const lockedPlaces = [
{ name: 'پارک کوهسنگی', note: 'خارج از محدودهٔ فعلی · به‌زودی' },
{ name: 'حرم و مرکز شهر', note: 'خارج از محدودهٔ فعلی · به‌زودی' },
{
name: 'پارک کوهسنگی',
note: 'خارج از محدودهٔ فعلی · به‌زودی',
},
{
name: 'حرم و مرکز شهر',
note: 'خارج از محدودهٔ فعلی · به‌زودی',
},
];
export const START = { machineId: 'factory' };
export const START = {
machineId: 'factory',
};
export const CITY_START = 'mellat-park';
/**
* Runs the machine by id operation for this subsystem.
* @param {*} id - id.
* @returns {*} Operation result, when applicable.
*/
export const machineById = (id) => machines.find((m) => m.id === id) ?? null;