// casegen/citizens.js — генерація мешканців району const N = require('./names'); const { allUnits, allJobs } = require('./district'); const { pick, chance, shuffle, ri } = require('./rng'); const BLOOD = ['O(I) Rh+', 'O(I) Rh+', 'A(II) Rh+', 'A(II) Rh+', 'B(III) Rh+', 'AB(IV) Rh+', 'O(I) Rh−', 'A(II) Rh−']; const PRINTS = ['дуга', 'петля', 'петля', 'завиток', 'завиток']; function makeCitizens(r, district) { const citizens = []; const usedNames = new Set(), usedPhones = new Set(), usedDna = new Set(); let nextId = 1; function person(sex, last, ageRange) { let first, full; do { first = pick(r, sex === 'ч' ? N.MALE : N.FEMALE); full = `${first} ${last}`; } while (usedNames.has(full)); usedNames.add(full); const age = ri(r, ageRange[0], ageRange[1]); const height = sex === 'ч' ? ri(r, 165, 195) : ri(r, 152, 183); let phone; do { phone = `+380${pick(r, ['50', '63', '66', '67', '68', '73', '95', '96', '97', '98', '99'])}${String(ri(r, 0, 9999999)).padStart(7, '0')}`; } while (usedPhones.has(phone)); usedPhones.add(phone); let dna; do { dna = Array.from({ length: 8 }, () => ri(r, 0, 15)); } while (usedDna.has(dna.join(','))); usedDna.add(dna.join(',')); return { id: 'c' + nextId++, name: full, first, last, sex, age, birthYear: 2026 - age, blood: pick(r, BLOOD), height, shoe: Math.max(35, Math.min(46, Math.round(height * 0.24) + ri(r, -1, 1))), printType: pick(r, PRINTS), printSeed: ri(r, 1, 2 ** 30), coat: pick(r, N.COATS), smoker: chance(r, 0.3), dog: chance(r, 0.2) ? pick(r, N.DOG_NAMES) : null, tattoo: chance(r, 0.25) ? pick(r, N.TATTOOS) : null, phone, dna, home: null, job: null, workplace: null, spouse: null }; } const unitList = allUnits(district); const sizes = {}; shuffle(r, unitList.filter(u => u[0] !== 'C')).forEach((u, i) => sizes[u] = i < 3 ? 1 : pick(r, [1, 2, 2, 3, 3, 4])); for (const u of unitList) if (u[0] === 'C') sizes[u] = pick(r, [1, 1, 2]); for (const unit of unitList) { const dorm = unit[0] === 'C'; const size = sizes[unit]; const last = pick(r, N.SURNAMES); if (size === 1) { const p = person(pick(r, ['ч', 'ж']), last, dorm ? [19, 45] : [25, 74]); p.home = unit; citizens.push(p); } else { const a = person('ч', last, [26, 68]); const b = person('ж', chance(r, 0.7) ? last : pick(r, N.SURNAMES), [Math.max(22, a.age - 8), Math.min(70, a.age + 8)]); if (!dorm) { a.spouse = b.id; b.spouse = a.id; } a.home = b.home = unit; citizens.push(a, b); for (let k = 2; k < size; k++) { const kid = person(pick(r, ['ч', 'ж']), last, [18, Math.max(19, a.age - 22)]); kid.home = unit; citizens.push(kid); } } } const jobs = shuffle(r, allJobs(district)); const workers = shuffle(r, citizens.filter(c => c.age <= 65)); workers.slice(0, jobs.length).forEach((c, i) => { c.job = jobs[i].title; c.workplace = jobs[i].building; }); for (const c of citizens) if (!c.job) c.job = c.age > 62 ? 'пенсіонер' : c.age < 23 ? 'студент' : 'тимчасово не працює'; return citizens; } module.exports = { makeCitizens };