Spaces:
Sleeping
Sleeping
Download document/fundamentacao.py from gui-sparim/teste_docs: direct link, hf CLI and curl.
- Browser
- Download file 8.72 kB
-
https://huggingface.co/spaces/gui-sparim/teste_docs/resolve/main/document/fundamentacao.py
- Command line
-
hf download hf://spaces/gui-sparim/teste_docs/document/fundamentacao.py
-
curl -L -o fundamentacao.py https://huggingface.co/spaces/gui-sparim/teste_docs/resolve/main/document/fundamentacao.py
8.72 kB
| """Documentary framing equivalent to MESA modelFoundation/globalFoundation. | |
| No valuation is recalculated. Missing evidence remains pending. Equivalence is | |
| checked against MESA's JavaScript, including the per-item minima. | |
| """ | |
| from decimal import Decimal, InvalidOperation | |
| from .mesa_content import content_for | |
| POINTS = {'Grau III': 3, 'Grau II': 2, 'Grau I': 1, 'Sem enquadramento': 0} | |
| def number(value): | |
| try: | |
| if value is None or value == '' or isinstance(value, bool): | |
| return None | |
| text = str(value) | |
| if ',' in text: | |
| text = text.replace('.', '').replace(',', '.') | |
| result = Decimal(text) | |
| return result if result.is_finite() else None | |
| except (InvalidOperation, ValueError): | |
| return None | |
| def grade(points): | |
| return {3: 'Grau III', 2: 'Grau II', 1: 'Grau I', 0: 'Sem enquadramento'}.get(points, 'Pendente') | |
| def threshold(value, limits): | |
| value = number(value) | |
| if value is None: | |
| return None | |
| return next((3-i for i, limit in enumerate(limits) if value <= Decimal(str(limit))), 0) | |
| def model_foundation(source): | |
| terrain = source.get('terreno') or {} | |
| state = terrain.get('fundamentacaoModelo') or {} | |
| context = terrain.get('contextoModelo') or {} | |
| evidence = context.get('normativeEvidence') or {} | |
| evaluation = terrain.get('avaliacao') or {} | |
| content = content_for(source) | |
| items = [] | |
| def add(key, label, points, detail=''): | |
| items.append({'key': key, 'label': label, 'points': points, 'grade': grade(points), 'detail': detail}) | |
| for key, label in [('caracterizacao', 'Caracterização do imóvel avaliando'), ('identificacaoDados', 'Identificação dos dados de mercado')]: | |
| saved = state.get(key) or {} | |
| selected = saved.get('grau') | |
| desc = content.get('descricoes_modelo', {}).get(key, {}).get(selected, '') | |
| detail = ' '.join(filter(None, [desc, saved.get('justificativa')])) | |
| add(key, label, POINTS.get(selected), detail or 'Enquadramento não informado pelo avaliador.') | |
| n, k = number(evidence.get('n')), number(evidence.get('k')) | |
| qty = next((points for mult, points in [(6, 3), (4, 2), (3, 1)] if n >= mult*(k+1)), 0) if n is not None and k is not None and k >= 0 else None | |
| add('quantidadeDados', 'Quantidade de dados de mercado', qty, f'n = {n}; k = {k}.' if qty is not None else 'n e k indisponíveis no contexto salvo.') | |
| extrap = POINTS.get(evaluation.get('fundamentacao')) | |
| if extrap is None and 'qtd_extrapolacoes' in evaluation: | |
| count = max(Decimal(0),number(evaluation['qtd_extrapolacoes']) or Decimal(0)) | |
| impact = number(evaluation.get('perc_ext')) or Decimal(0) | |
| severe = any(isinstance(item, dict) and item.get('status') == 'grave' for item in (evaluation.get('extrapolacoes') or {}).values()) | |
| extrap = 0 if severe or (impact is not None and impact > 20) else 3 if count == 0 else 2 if count == 1 and impact is not None and impact <= 15 else 1 | |
| count_text = evaluation.get('qtd_extrapolacoes') | |
| impact_text = evaluation.get('perc_ext') | |
| detail = 'Nenhuma variável extrapolada.' if count_text == 0 else f"Variáveis extrapoladas: {count_text if count_text is not None else 'não informado'}." + (f' Impacto: {impact_text}%.' if impact_text is not None else '') | |
| add('extrapolacao', 'Extrapolação', extrap, detail) | |
| pvalues = [(item.get('name', ''), number(item.get('pValue'))) for item in evidence.get('regressorPValues', []) if isinstance(item, dict)] | |
| worst = max(((name, p) for name, p in pvalues if p is not None), key=lambda item: item[1], default=('', None)) | |
| add('significanciaRegressores', 'Significância dos regressores', threshold(worst[1], [.1,.2,.3]), f'Maior p-valor: {worst[1]} ({worst[0]}).' if worst[1] is not None else 'p-valores indisponíveis.') | |
| add('significanciaModelo', 'Teste F', threshold(evidence.get('fPValue'), [.01,.02,.05]), f"p-valor: {evidence.get('fPValue', 'não informado')}.") | |
| by_key = {item['key']: item['points'] for item in items} | |
| p = [by_key[key] for key in ['caracterizacao','quantidadeDados','identificacaoDados','extrapolacao','significanciaRegressores','significanciaModelo']] | |
| total = sum(value for value in p if value is not None) | |
| result = 'Pendente' | |
| requirements = state.get('requisitosGrauIII') or {} | |
| req_keys = [item['key'] for item in content.get('requisitos_modelo', [])] | |
| candidate = all(value is not None for value in p) and total >= 16 and all(value >= minimum for value, minimum in zip(p,[2,3,2,3,3,3])) | |
| missing_req = candidate and any(requirements.get(key) not in ('sim','nao',True,False) for key in req_keys) | |
| if all(value is not None for value in p) and not missing_req: | |
| if candidate and all(requirements.get(key) in ('sim',True) for key in req_keys): result = 'Grau III' | |
| elif total >= 10 and all(value >= minimum for value, minimum in zip(p,[1,2,1,2,2,2])): result = 'Grau II' | |
| elif all(value >= 1 for value in p): result = 'Grau I' | |
| else: result = 'Sem enquadramento' | |
| return {'items': items, 'totalPoints': total, 'grade': result, 'requirements': requirements, 'missingRequirements': bool(missing_req)} | |
| def construction_foundation(source): | |
| construction = source.get('construcao') or {} | |
| saved = construction.get('fundamentacaoMqc') or (construction.get('avaliacao') or {}).get('fundamentacaoMqc') or {} | |
| defs = saved.get('definitions') or {} | |
| # Labels are extracted from the very function that assigns the MESA scores. | |
| import re | |
| rule = content_for(source)['funcoes_mqc']['calcularEnquadramento'] | |
| options = re.findall(r"definitions\.(\w+) === '([^']+)' \? (\d)", rule) | |
| items = [] | |
| for key, label in [('formaCub','Custo direto'),('tipoBdi','BDI'),('depreciacao','Depreciação física')]: | |
| value = defs.get(key) | |
| points = next((int(score) for field, text, score in options if field == key and value == text), 1 if value else None) | |
| items.append({'label':label,'points':points,'grade':grade(points),'detail':value or 'Critério não informado.'}) | |
| p = [item['points'] for item in items] | |
| total = sum(value for value in p if value is not None) | |
| result = 'Pendente' | |
| if all(value is not None for value in p): | |
| if total >= 7 and p[0] == 3 and min(p[1:]) >= 2: result = 'Grau III' | |
| elif total >= 5 and p[0] >= 2 and p[1] >= 2: result = 'Grau II' | |
| elif total >= 3: result = 'Grau I' | |
| else: result = 'Fora dos critérios' | |
| return {'items':items,'totalPoints':total,'grade':result} | |
| def global_foundation(source): | |
| terrain = model_foundation(source) | |
| construction = construction_foundation(source) | |
| result = source.get('resultadoComposicao') or {} | |
| vt = number((source.get('terreno') or {}).get('valorTotal')) | |
| vc = number((source.get('construcao') or {}).get('valorTotal')) | |
| # calculate(year).beforeFc in MESA is the sum of these two saved components. | |
| total_value = vt+vc if vt is not None and vc is not None else None | |
| items = [] | |
| for label, value, foundation in [('Terreno',vt,terrain),('Construções',vc,construction)]: | |
| share = value/total_value if value is not None and total_value is not None and total_value > 0 else None | |
| reduced = value is not None and value > 0 and share is not None and share < Decimal('.15') | |
| points = 2 if reduced else POINTS.get(foundation['grade']) | |
| # Global MESA only recognises the three positive grades. | |
| if not reduced and points == 0: points = None | |
| items.append({'label':label,'grade':grade(points),'points':points,'detail':'Participação inferior a 15%; atribuídos dois pontos ao item.' if reduced else f"Fundamentação do componente: {foundation['grade']}.", 'share':share}) | |
| fc = str((source.get('fundamentacaoGlobal') or {}).get('fatorComercializacao') or '') | |
| option = next((item for item in content_for(source)['criterios_fc'] if item['value'] == fc), {}) | |
| items.append({'label':'Fator de comercialização','grade':option.get('grade','Pendente'),'points':option.get('points'),'detail':option.get('label','Critério do Fc não informado.')}) | |
| p = [item['points'] for item in items] | |
| total = sum(value for value in p if value is not None) | |
| result_grade = 'Pendente' | |
| if all(value is not None for value in p): | |
| if total >= 8 and p[0] == p[1] == 3 and p[2] >= 2: result_grade = 'Grau III' | |
| elif total >= 5 and p[0] >= 2 and p[1] >= 2: result_grade = 'Grau II' | |
| elif total >= 3 and min(p) >= 1: result_grade = 'Grau I' | |
| else: result_grade = 'Sem enquadramento' | |
| return {'items':items,'totalPoints':total,'grade':result_grade,'terrain':terrain,'construction':construction} | |