refactor: centralize brand, company info, assets and Persian strings
Phase 1 of turning the game into the company landing page. - Add src/config/company.js with name, tagline, contact, about and the product line, plus a brand palette built around #00a693 (contrast checked); placeholders are marked TODO(company). - Add src/config/assets.js listing every loaded file with its expected format; placeholders are marked TODO(asset). - Move all Persian interface text, dialogue, missions and scenery text into src/i18n/fa.js; components and game code read from it. - Expose the palette as CSS variables (--color-primary and shades) and Tailwind colours, and use it for 3D materials and map drawings. - Fix the arrival line that still called the manager's car a white pickup. - Add tests that block hard-coded Persian text and low-contrast colours. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+21
-18
@@ -1,40 +1,43 @@
|
||||
import { COMPANY } from '../config/company.js';
|
||||
import { strings } from '../i18n/fa.js';
|
||||
|
||||
// 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: 'کارخانه',
|
||||
label: strings.categories.factory,
|
||||
icon: '🏭',
|
||||
},
|
||||
park: {
|
||||
label: 'پارک',
|
||||
label: strings.categories.park,
|
||||
icon: '🌳',
|
||||
},
|
||||
university: {
|
||||
label: 'دانشگاه',
|
||||
label: strings.categories.university,
|
||||
icon: '🎓',
|
||||
},
|
||||
school: {
|
||||
label: 'مدرسه',
|
||||
label: strings.categories.school,
|
||||
icon: '🏫',
|
||||
},
|
||||
metro: {
|
||||
label: 'ایستگاه مترو',
|
||||
label: strings.categories.metro,
|
||||
icon: 'Ⓜ',
|
||||
},
|
||||
mall: {
|
||||
label: 'مرکز خرید',
|
||||
label: strings.categories.mall,
|
||||
icon: '🛍',
|
||||
},
|
||||
test: {
|
||||
label: 'نقطهٔ آزمایشی GPS',
|
||||
label: strings.categories.test,
|
||||
icon: '🧪',
|
||||
},
|
||||
};
|
||||
const ALL_DAY = [7 * 60, 23 * 60];
|
||||
export const FACTORY = {
|
||||
name: 'شرکت روبات مارکت',
|
||||
tagline: 'سازندهٔ دستگاههای وندینگ هوشمند',
|
||||
address: 'بزرگراه مشهد–چناران، خیابان کاله، کنار پارک علم و فناوری خراسان',
|
||||
name: COMPANY.name,
|
||||
tagline: COMPANY.tagline,
|
||||
address: COMPANY.contact.address,
|
||||
// Centre of the compound and the direction of its driveway (towards the gate on Kaleh Street).
|
||||
center: {
|
||||
x: -10308.4,
|
||||
@@ -48,14 +51,14 @@ export const FACTORY = {
|
||||
export const machines = [
|
||||
{
|
||||
id: 'factory',
|
||||
name: 'دستگاه دفتر فنی مهندسی',
|
||||
name: strings.places.officeMachine,
|
||||
category: 'factory',
|
||||
address: `${FACTORY.address}، ساختمان اداری، دفتر فنی مهندسی`,
|
||||
address: strings.places.officeAddress(FACTORY.address),
|
||||
anchor: null,
|
||||
hours: [0, 24 * 60],
|
||||
priceFactor: 0.5,
|
||||
products: ['water', 'juice', 'tea', 'biscuit', 'chocolate'],
|
||||
note: 'دستگاه دفتر برنامهنویسها؛ نصف قیمت برای مهمانهای کارخانه',
|
||||
note: strings.places.officeNote,
|
||||
},
|
||||
{
|
||||
id: 'mellat-park',
|
||||
@@ -168,10 +171,10 @@ export const machines = [
|
||||
*/
|
||||
const testPoint = (n, lat, lon) => ({
|
||||
id: `test-${n}`,
|
||||
name: `نقطهٔ آزمایشی ${['۱', '۲', '۳'][n - 1]}`,
|
||||
name: strings.places.testPoint(n.toLocaleString('fa-IR')),
|
||||
category: 'test',
|
||||
test: true,
|
||||
address: `کنار کارخانهٔ روبات مارکت · ${lat.toFixed(6)}, ${lon.toFixed(6)}`,
|
||||
address: strings.places.testAddress(`${lat.toFixed(6)}, ${lon.toFixed(6)}`),
|
||||
anchor: null,
|
||||
spot: {
|
||||
lat,
|
||||
@@ -180,7 +183,7 @@ const testPoint = (n, lat, lon) => ({
|
||||
hours: [0, 24 * 60],
|
||||
priceFactor: 0.5,
|
||||
products: ['water', 'biscuit'],
|
||||
note: 'برای آزمایش حالت دنیای واقعی: با گوشی تا اینجا راه بروید',
|
||||
note: strings.places.testNote,
|
||||
});
|
||||
machines.push(
|
||||
testPoint(1, 36.450276, 59.423431),
|
||||
@@ -192,11 +195,11 @@ machines.push(
|
||||
export const lockedPlaces = [
|
||||
{
|
||||
name: 'پارک کوهسنگی',
|
||||
note: 'خارج از محدودهٔ فعلی · بهزودی',
|
||||
note: strings.places.comingSoon,
|
||||
},
|
||||
{
|
||||
name: 'حرم و مرکز شهر',
|
||||
note: 'خارج از محدودهٔ فعلی · بهزودی',
|
||||
note: strings.places.comingSoon,
|
||||
},
|
||||
];
|
||||
export const START = {
|
||||
|
||||
@@ -1,47 +1,5 @@
|
||||
/** Display-only machine prices in rial, independent of the consumable economy. */
|
||||
export const SHOWROOM_CATALOG = [
|
||||
{
|
||||
id: 'rm-35',
|
||||
category: 'warm-vending',
|
||||
name: 'روبات مارکت ۳۵ کانال',
|
||||
shortLabel: '۳۵ کانال',
|
||||
channels: 35,
|
||||
priceLabel: '4,680,000,000 ریال',
|
||||
priceNumeric: 4680000000,
|
||||
description:
|
||||
'یخچالدار، ۳۵ کانال اختصاصی، سیستم خنککننده قدرتمند، تحویل نرم، مدیریت آنلاین ۲۴ ساعته.',
|
||||
highlights: ['یخچالدار', '۳۵ کانال اختصاصی', 'تحویل نرم', 'مدیریت آنلاین ۲۴ ساعته'],
|
||||
image: '/images/machine-35-base.webp',
|
||||
imageAlt: '/images/machine-35-white.webp',
|
||||
gif: '/gifs/machine-35.gif',
|
||||
},
|
||||
{
|
||||
id: 'rm-48',
|
||||
category: 'warm-vending',
|
||||
name: 'روبات مارکت ۴۸ کانال',
|
||||
shortLabel: '۴۸ کانال',
|
||||
channels: 48,
|
||||
priceLabel: '5,480,000,000 ریال',
|
||||
priceNumeric: 5480000000,
|
||||
description: 'یخچالدار، ۴۸ کانال اختصاصی، قابلیتهای پیشرفته مدیریت آنلاین و تحویل کالا.',
|
||||
highlights: ['یخچالدار', '۴۸ کانال اختصاصی', 'مدیریت آنلاین پیشرفته', 'تحویل هوشمند کالا'],
|
||||
image: '/images/machine-48-base.webp',
|
||||
imageAlt: '/images/machine-48-white.webp',
|
||||
gif: '/gifs/machine-48.gif',
|
||||
},
|
||||
{
|
||||
id: 'rm-60',
|
||||
category: 'warm-vending',
|
||||
name: 'روبات مارکت ۶۰ کانال',
|
||||
shortLabel: '۶۰ کانال',
|
||||
channels: 60,
|
||||
priceLabel: '5,980,000,000 ریال',
|
||||
priceNumeric: 5980000000,
|
||||
description: 'یخچالدار، ۶۰ کانال اختصاصی برای کسبوکارهای پرتردد.',
|
||||
highlights: ['یخچالدار', '۶۰ کانال اختصاصی', 'مناسب اماکن پرتردد', 'ظرفیت بالا'],
|
||||
image: '/images/machine-60-base.webp',
|
||||
imageAlt: '/images/machine-60-white.webp',
|
||||
gif: '/gifs/machine-60.gif',
|
||||
},
|
||||
];
|
||||
import { COMPANY } from '../config/company.js';
|
||||
|
||||
/** Display-only machine models; the product line itself lives in config/company.js. */
|
||||
export const SHOWROOM_CATALOG = COMPANY.products;
|
||||
export const SHOWROOM_REACH = 4;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { strings } from '../i18n/fa.js';
|
||||
|
||||
// Every vehicle in the factory yard is painted this gloss black.
|
||||
export const VEHICLE_BLACK = '#0c0d0f';
|
||||
|
||||
@@ -7,16 +9,8 @@ export const ENTER_DISTANCE = 4.5;
|
||||
// Above this speed (m/s) the player has to stop before getting off.
|
||||
export const EXIT_MAX_SPEED = 3;
|
||||
|
||||
// Persian names shown in prompts. `bmw` is the family car parked beside the start point.
|
||||
export const VEHICLE_LABELS = {
|
||||
bmw: 'بیامو',
|
||||
bugatti: 'بوگاتی',
|
||||
lamborghini: 'لامبورگینی',
|
||||
mazda: 'مزدا',
|
||||
nissan: 'نیسان',
|
||||
apache: 'موتور آپاچی',
|
||||
traffic: 'ماشین',
|
||||
};
|
||||
// Names shown in prompts, from the strings file. `bmw` is the family car beside the start point.
|
||||
export const VEHICLE_LABELS = strings.vehicles;
|
||||
|
||||
// Brands parked in the staff bays, in bay order. Mr Mohammadi arrives in the Bugatti.
|
||||
export const STAFF_CAR_BRANDS = ['lamborghini', 'mazda', 'nissan'];
|
||||
|
||||
Reference in New Issue
Block a user