48 lines
1.5 KiB
JavaScript
48 lines
1.5 KiB
JavaScript
// PROPOSTA DIDACTICA. Dados sinteticos; nao integrado no Laravel ou no portal.
|
|
// Nao e IA nem apuramento oficial de lacunas. Nao modela alocacao entre projectos.
|
|
export function observedGap({
|
|
demand,
|
|
available,
|
|
context,
|
|
supplyContext,
|
|
sourceValid,
|
|
}) {
|
|
if (typeof sourceValid !== 'boolean')
|
|
throw new TypeError('Validade explicita obrigatoria');
|
|
const dimensions = [
|
|
'occupation',
|
|
'qualification',
|
|
'territory',
|
|
'period',
|
|
'unit',
|
|
];
|
|
for (const key of dimensions) {
|
|
if (
|
|
typeof context?.[key] !== 'string' ||
|
|
!context[key].trim() ||
|
|
typeof supplyContext?.[key] !== 'string' ||
|
|
!supplyContext[key].trim()
|
|
) {
|
|
throw new TypeError('Contexto completo obrigatorio');
|
|
}
|
|
}
|
|
for (const value of [demand, available]) {
|
|
if (value !== null && (!Number.isSafeInteger(value) || value < 0)) {
|
|
throw new TypeError('Quantidade inteira nao negativa ou null');
|
|
}
|
|
}
|
|
if (!sourceValid) return { state: 'expired', people: null };
|
|
if (
|
|
context.unit !== 'people' ||
|
|
dimensions.some((key) => context[key] !== supplyContext[key])
|
|
) {
|
|
return { state: 'incomparable', people: null };
|
|
}
|
|
if (demand === null || available === null)
|
|
return { state: 'insufficient_data', people: null };
|
|
return {
|
|
state: 'observed_unvalidated',
|
|
people: Math.max(0, demand - available),
|
|
};
|
|
}
|