PageSourceSearch

https://tecdvr-v7.web.app/js/tec-impianti-vista-luogo.js?v=20.374.20

js tecdvr-v7.web.app collected 2026-10-03 12:39:38 UTC 11,211 bytes, 250 lines download raw bytes

1/**
2 * tec-impianti-vista-luogo.js — v20.373.118
3 *
4 * ── LA REGOLA ────────────────────────────────────────────────────────────────────────────────
5 * UN IMPIANTO STA NELL'EDIFICIO CHE LO CONTIENE — e il DVR lo racconta DOVE STA.
6 *
7 * tec-impianti-luogo-migrazione.js ha gia' stabilito che gli impianti vivono nel Luogo. Da li'
8 * syncImpiantiGrafoToSede produce una proiezione piatta di sede (d.imp*) che serve ai lettori
9 * legacy (readiness, profilo). Quella proiezione e' UNO SPECCHIO, non la fonte, e ha un limite
10 * strutturale che non e' un bug da tappare ma una conseguenza della sua forma: e' UN record per
11 * N edifici. Se la palazzina uffici ha la DiCo e il capannone no, un record solo puo' raccontare
12 * un fatto solo — e il fatto che sopravvive e' quello del luogo che arriva prima.
13 *
14 * Verificato in laboratorio, non dedotto (due luoghi, impianti divergenti):
15 *   luogo A: DiCo presente,  luce emergenza si,   idrico antincendio no
16 *   luogo B: DiCo MANCANTE,  luce emergenza NO,   idrico antincendio si (idranti UNI45)
17 *   §1.4 stampava: «DiCo D.M. 37/08 presente», «Emergenza: presente», «Assenti: idrico
18 *   antincendio» — mentre d.impIdricoAI_tipo valeva 'idranti_uni45'. Due non conformita'
19 *   cancellate e un record impossibile (assente + con idranti) prodotto dalla fusione.
20 *
21 * Questo modulo e' il proprietario unico della vista impianti PER LUOGO. Non duplica la
22 * presentazione: proietta ogni singolo luogo nella stessa forma piatta che i lettori conoscono
23 * e la passa allo stesso identico costruttore (buildImpiantiDettaglioExport). Un solo motore,
24 * N inquadrature.
25 *
26 * Dichiara anche le DIVERGENZE: dove i luoghi non dicono la stessa cosa, il documento lo scrive.
27 * Il silenzio non assolve (art. 29 c.1).
28 */
29(function (g) {
30  'use strict';
31  var VERSION = '1.0.0';
32
33  function _S() { return g._tecImpiantiSync || null; }
34  function _EC() { return g._tecDvrExportClarity || null; }
35
36  function _hasVal(v) {
37    if (v == null) return false;
38    if (typeof v === 'string') return v.trim() !== '' && v.trim() !== '—';
39    if (typeof v === 'number') return !isNaN(v);
40    if (typeof v === 'boolean') return true;
41    return false;
42  }
43  function _s(v) { return v == null ? '' : String(v).trim(); }
44
45  /**
46   * Etichette leggibili delle chiavi piatte. Non inventate: derivate da UI_BLOCKS, cioe' dalle
47   * stesse parole che il tecnico legge sullo schermo mentre compila. Se una chiave non ha
48   * etichetta dichiarata NON si indovina: si restituisce la chiave, cosi' il buco si vede.
49   */
50  function mappaEtichette() {
51    var S = _S();
52    var out = {};
53    if (!S || !S.BLOCKS) return out;
54    var ui = S.UI_BLOCKS || [];
55    Object.keys(S.BLOCKS).forEach(function (bk) {
56      var def = S.BLOCKS[bk] || {};
57      var gk = def.grafoKeys || {};
58      var uiB = null;
59      for (var i = 0; i < ui.length; i++) { if (ui[i] && ui[i].key === bk) { uiB = ui[i]; break; } }
60      var etBlocco = (uiB && uiB.label) ? uiB.label : bk;
61      Object.keys(gk).forEach(function (sedeK) {
62        var campoGrafo = gk[sedeK];
63        var lab = '';
64        if (uiB && uiB.fields) {
65          for (var j = 0; j < uiB.fields.length; j++) {
66            if (uiB.fields[j] && uiB.fields[j].k === campoGrafo) { lab = uiB.fields[j].l; break; }
67          }
68        }
69        if (!lab && uiB && campoGrafo === (uiB.presentKey || 'presente')) lab = 'Presenza impianto';
70        out[sedeK] = { blocco: bk, etichettaBlocco: etBlocco, etichetta: lab || sedeK, campoGrafo: campoGrafo };
71      });
72    });
73    return out;
74  }
75
76  /** L'elenco dei luoghi. Una sola domanda, una sola risposta: si chiede a chi la possiede gia'. */
77  function luoghi(d, listOverride) {
78    if (Array.isArray(listOverride) && listOverride.length) return listOverride.filter(Boolean);
79    var PR = g._tecPorteReiLuogo;
80    if (PR && typeof PR.getLuoghiSync === 'function') {
81      try { var l = PR.getLuoghiSync(); if (l && l.length) return l.filter(Boolean); } catch (_e) {}
82    }
83    if (d && Array.isArray(d.ambientiSede) && d.ambientiSede.length) return d.ambientiSede.filter(Boolean);
84    var G = g._tecGrafo;
85    if (G && G.getGrafoCache) {
86      try {
87        var c = G.getGrafoCache();
88        if (c && c.luoghiSede && c.luoghiSede.length) return c.luoghiSede.filter(Boolean);
89        if (c && c.ambientiSede && c.ambientiSede.length) return c.ambientiSede.filter(Boolean);
90      } catch (_e2) {}
91    }
92    return [];
93  }
94
95  /** Proiezione piatta di UN SOLO luogo: la stessa forma della sede, ma di un edificio solo. */
96  function flatDiLuogo(amb) {
97    var S = _S();
98    var out = {};
99    if (!S || !S.BLOCKS || !S.sedeFromGrafoBlock || !amb) return out;
100    var imp = amb.impianti || {};
101    Object.keys(S.BLOCKS).forEach(function (bk) {
102      var part = S.sedeFromGrafoBlock(bk, imp[bk]);
103      Object.keys(part).forEach(function (k) { if (_hasVal(part[k])) out[k] = part[k]; });
104    });
105    return out;
106  }
107
108  function haImpianti(amb) {
109    var f = flatDiLuogo(amb);
110    return Object.keys(f).length > 0;
111  }
112
113  function nomeLuogo(amb, i) {
114    return _s(amb && (amb.nome || amb.denominazione || amb.label)) || ('Luogo ' + (i + 1));
115  }
116
117  function pianoLuogo(amb, d) {
118    var DV = g._tecLuogoDove;
119    if (DV && typeof DV.pianiDelLuogo === 'function') {
120      try {
121        var p = DV.pianiDelLuogo(amb, d);
122        if (p && p.ereditato) return p.ereditato;
123      } catch (_e) {}
124    }
125    return '';
126  }
127
128  /**
129   * La vista. Un blocco per luogo, costruito dallo stesso motore che costruisce quello di sede.
130   * @returns {{luoghi:Array, divergenze:Array, nLuoghi:number, perLuogo:boolean, fonte:string}}
131   */
132  function vistaPerLuogo(d, helpers, listOverride) {
133    d = d || {};
134    helpers = helpers || {};
135    var EC = _EC();
136    var list = luoghi(d, listOverride).filter(haImpianti);
137    var out = { luoghi: [], divergenze: [], nLuoghi: list.length, perLuogo: false, fonte: 'grafo (impianti del luogo)' };
138    if (!EC || typeof EC.buildImpiantiDettaglioExport !== 'function') { out.fonte = 'motore di presentazione non disponibile'; return out; }
139    list.forEach(function (amb, i) {
140      var flat = flatDiLuogo(amb);
141      var built = EC.buildImpiantiDettaglioExport(flat, helpers);
142      out.luoghi.push({
143        id: _s(amb && amb.id) || ('l' + i),
144        nome: nomeLuogo(amb, i),
145        piano: pianoLuogo(amb, d),
146        rows: (built && built.rows) || [],
147        assentiNote: (built && built.assentiNote) || null,
148        nCampi: Object.keys(flat).length
149      });
150    });
151    out.divergenze = divergenze(d, list);
152    // Una sola inquadratura basta solo se c'e' un solo edificio con impianti. Con due o piu',
153    // raccontarne uno solo significa scegliere quale non conformita' nascondere.
154    out.perLuogo = list.length > 1;
155    return out;
156  }
157
158  /**
159   * Dove i luoghi non dicono la stessa cosa. Confronta le proiezioni piatte campo per campo:
160   * ogni chiave su cui almeno due luoghi portano valori diversi e' una divergenza.
161   */
162  function divergenze(d, listOverride) {
163    var list = (Array.isArray(listOverride) ? listOverride : luoghi(d)).filter(haImpianti);
164    var et = mappaEtichette();
165    var perCampo = {};
166    list.forEach(function (amb, i) {
167      var flat = flatDiLuogo(amb);
168      Object.keys(flat).forEach(function (k) {
169        perCampo[k] = perCampo[k] || [];
170        perCampo[k].push({ luogo: nomeLuogo(amb, i), id: _s(amb && amb.id), valore: _s(flat[k]) });
171      });
172    });
173    var out = [];
174    Object.keys(perCampo).forEach(function (k) {
175      var vals = perCampo[k];
176      var distinti = {};
177      vals.forEach(function (v) { distinti[v.valore] = true; });
178      if (Object.keys(distinti).length < 2) return;
179      var meta = et[k] || { etichetta: k, etichettaBlocco: '', blocco: '' };
180      out.push({
181        campo: k,
182        blocco: meta.blocco,
183        etichettaBlocco: meta.etichettaBlocco,
184        etichetta: meta.etichetta,
185        valori: vals
186      });
187    });
188    out.sort(function (a, b) {
189      if (a.etichettaBlocco !== b.etichettaBlocco) return a.etichettaBlocco < b.etichettaBlocco ? -1 : 1;
190      return a.etichetta < b.etichetta ? -1 : 1;
191    });
192    return out;
193  }
194
195  /**
196   * L'avvertenza che accompagna la sintesi di sede quando i luoghi divergono. Non e' una nota di
197   * stile: e' la dichiarazione che la riga di sintesi NON e' la fotografia di tutti gli edifici.
198   */
199  function avvisoDivergenze(div) {
200    div = div || [];
201    if (!div.length) return null;
202    var campi = div.slice(0, 6).map(function (x) {
203      return x.etichetta + ' (' + x.valori.map(function (v) { return v.luogo + ': ' + (v.valore || '—'); }).join(' · ') + ')';
204    });
205    return 'Gli impianti differiscono da un edificio all\'altro: il dettaglio per luogo di lavoro '
206      + 'riportato qui sopra e\' la fonte, la sintesi di sede e\' una proiezione e non puo\' rappresentare '
207      + 'tutti gli edifici contemporaneamente. Campi divergenti: ' + campi.join('; ')
208      + (div.length > 6 ? ('; e altri ' + (div.length - 6)) : '') + '.';
209  }
210
211  /** Self-test in-processo: la vista non fonde, non inventa, non perde una non conformita'. */
212  function selfTest() {
213    var errs = [];
214    var list = [
215      { id: 'A', nome: 'Palazzina Uffici', impianti: {
216        elettrico: { presente: 'si', ubicQEgen: 'atrio', dichConf: 'presente' },
217        illuminazione: { sicurezzaPresente: 'si', sicurezzaTipo: 'autonoma' },
218        idricoAntincendio: { presente: 'no' } } },
219      { id: 'B', nome: 'Capannone', impianti: {
220        elettrico: { presente: 'si', ubicQEgen: 'locale_tecnico', dichConf: 'mancante' },
221        illuminazione: { sicurezzaPresente: 'no' },
222        idricoAntincendio: { presente: 'si', tipo: 'idranti_uni45' } } }
223    ];
224    var v = vistaPerLuogo({}, {}, list);
225    if (v.luoghi.length !== 2) errs.push('attesi 2 luoghi, trovati ' + v.luoghi.length);
226    if (!v.perLuogo) errs.push('con 2 edifici la vista deve essere per luogo');
227    var testoB = (v.luoghi[1] ? v.luoghi[1].rows : []).map(function (r) { return r[1]; }).join(' | ');
228    if (testoB.indexOf('MANCANTE') < 0) errs.push('la DiCo mancante del capannone non compare');
229    var testoA = (v.luoghi[0] ? v.luoghi[0].rows : []).map(function (r) { return r[1]; }).join(' | ');
230    if (testoA.indexOf('MANCANTE') >= 0) errs.push('la DiCo mancante e finita sulla palazzina');
231    if (testoB.indexOf('ASSENTE') < 0) errs.push('la luce di emergenza assente del capannone non compare');
232    var d1 = v.divergenze.filter(function (x) { return x.campo === 'impEl_dichConf'; })[0];
233    if (!d1) errs.push('divergenza su impEl_dichConf non rilevata');
234    return { ok: errs.length === 0, errors: errs };
235  }
236
237  g._tecImpiantiVistaLuogo = {
238    VERSION: VERSION,
239    luoghi: luoghi,
240    flatDiLuogo: flatDiLuogo,
241    haImpianti: haImpianti,
242    nomeLuogo: nomeLuogo,
243    pianoLuogo: pianoLuogo,
244    mappaEtichette: mappaEtichette,
245    vistaPerLuogo: vistaPerLuogo,
246    divergenze: divergenze,
247    avvisoDivergenze: avvisoDivergenze,
248    selfTest: selfTest
249  };
250})(typeof window !== 'undefined' ? window : this);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.