spb/uqo-imm1003
Public
JavaScript 68%
CSS 32%
1// entrainement-imm1003.js — générateurs de problèmes à données aléatoires (IMM1003)2// Chaque générateur : { id, title, ch, url, gen(R) → { enonce, answer, unit, tol, steps } }3// R : utilitaires aléatoires fournis par app.js (R.int(a,b), R.pick(arr), R.step(a,b,step), R.money(v), R.pct(v), R.num(v,d))4window.UQO_TRAINING = [5 {6 id: "rpv", title: "RPV et mise de fonds", ch: "01", url: "/seance/01/#form-1-1",7 gen(R) {8 const prix = R.step(320000, 780000, 5000);9 const evalv = prix - R.step(0, 45000, 5000);10 const retenue = Math.min(prix, evalv);11 const pret = retenue * 0.8;12 const mise = prix - pret;13 return {14 enonce: `Une offre d’achat est acceptée à <b>${R.money(prix)}</b>. L’évaluation exigée par le prêteur conclut à <b>${R.money(evalv)}</b>. L’acheteur souhaite un prêt conventionnel (RPV maximal de 80 %). Quelle <b>mise de fonds</b> devra-t-il verser ?`,15 answer: mise, unit: "$", tol: 0.005,16 steps: `<p>1. Valeur retenue = la moindre du prix et de l’évaluation = ${R.money(retenue)}.</p><p>2. Prêt maximal = ${R.money(retenue)} × 80 % = ${R.money(pret)}.</p><p>3. Mise de fonds = prix − prêt = ${R.money(prix)} − ${R.money(pret)} = <b>${R.money(mise)}</b> (soit ${R.pct(mise / prix * 100, 1)} du prix).</p>`,17 };18 },19 },20 {21 id: "mutation", title: "Droits de mutation (barème 2026)", ch: "01", url: "/seance/01/#s-1-6-3",22 gen(R) {23 const prix = R.step(180000, 900000, 1000);24 const t1 = Math.min(prix, 62900) * 0.005;25 const t2 = Math.max(0, Math.min(prix, 315000) - 62900) * 0.01;26 const t3 = Math.max(0, prix - 315000) * 0.015;27 const tot = t1 + t2 + t3;28 return {29 enonce: `Calculez les <b>droits de mutation</b> exigibles pour une propriété acquise <b>${R.money(prix)}</b> (barème de base 2026 : 0,5 % jusqu’à 62 900 $ ; 1,0 % de 62 900 $ à 315 000 $ ; 1,5 % au-delà ; aucun taux municipal majoré).`,30 answer: tot, unit: "$", tol: 0.005,31 steps: `<p>Tranche 1 : 62 900 × 0,5 % = ${R.money2(t1)}.</p><p>Tranche 2 : ${prix > 315000 ? "(315 000 − 62 900)" : "(" + R.money(prix) + " − 62 900)"} × 1,0 % = ${R.money2(t2)}.</p>${prix > 315000 ? `<p>Tranche 3 : (${R.money(prix)} − 315 000) × 1,5 % = ${R.money2(t3)}.</p>` : "<p>Pas de tranche 3 (prix ≤ 315 000 $).</p>"}<p>Total : <b>${R.money2(tot)}</b>.</p>`,32 };33 },34 },35 {36 id: "temporel", title: "Ajustement temporel d’un comparable", ch: "08", url: "/seance/08/#s-8-4",37 gen(R) {38 const prix = R.step(300000, 700000, 1000);39 const g = R.pick([3, 4, 5, 6, 8]);40 const mois = R.int(2, 14);41 const adj = prix * g / 100 / 12 * mois;42 return {43 enonce: `Un comparable s’est vendu <b>${R.money(prix)}</b> il y a <b>${mois} mois</b>. Le marché progresse de <b>${g} % par an</b> (ajustement linéaire). Quel est le <b>prix ajusté</b> pour le temps ?`,44 answer: prix + adj, unit: "$", tol: 0.003,45 steps: `<p>Taux mensuel = ${g} % ÷ 12 = ${R.num(g / 12, 4)} %.</p><p>Ajustement = ${R.money(prix)} × ${R.num(g / 12, 4)} % × ${mois} = ${R.money(adj)} (positif : le marché a monté depuis la vente).</p><p>Prix ajusté = ${R.money(prix)} + ${R.money(adj)} = <b>${R.money(prix + adj)}</b>.</p>`,46 };47 },48 },49 {50 id: "netbrut", title: "Ajustements net et brut", ch: "09", url: "/seance/09/#s-9-4",51 gen(R) {52 const prix = R.step(350000, 650000, 5000);53 const a = [R.step(-30000, 30000, 1000), R.step(-25000, 25000, 1000), R.step(-20000, 20000, 1000), R.step(-15000, 15000, 1000)].map((x) => (x === 0 ? 5000 : x));54 const net = a.reduce((s, x) => s + x, 0);55 const brut = a.reduce((s, x) => s + Math.abs(x), 0);56 return {57 enonce: `Un comparable vendu <b>${R.money(prix)}</b> reçoit quatre ajustements : ${a.map((x) => `<b>${x > 0 ? "+" : "−"}${R.money(Math.abs(x))}</b>`).join(", ")}. Quel est l’<b>ajustement brut</b>, en pourcentage du prix de vente ? (Répondez en %, ex. 12,5)`,58 answer: brut / prix * 100, unit: "%", tol: 0.01,59 steps: `<p>Net (somme algébrique) = ${R.money(net)} → ${R.pct(net / prix * 100)} ${Math.abs(net / prix) <= 0.15 ? "(≤ 15 %, acceptable)" : "(> 15 % : fiabilité réduite)"}.</p><p>Brut (somme des valeurs absolues) = ${R.money(brut)} → <b>${R.pct(brut / prix * 100)}</b> ${brut / prix <= 0.25 ? "(≤ 25 %, acceptable)" : "(> 25 % : comparable peu fiable)"}.</p>`,60 };61 },62 },63 {64 id: "capitalisation", title: "Capitalisation directe", ch: "11", url: "/seance/11/#s-11-1",65 gen(R) {66 const rne = R.step(38000, 260000, 500);67 const tga = R.pick([4.75, 5, 5.25, 5.5, 5.75, 6, 6.25, 6.5, 7]);68 return {69 enonce: `Le revenu net d’exploitation stabilisé d’un immeuble locatif est de <b>${R.money(rne)}</b> par année. Le taux global d’actualisation extrait du marché est de <b>${R.num(tga, 2)} %</b>. Quelle est l’<b>indication de valeur</b> par capitalisation directe ?`,70 answer: rne / (tga / 100), unit: "$", tol: 0.003,71 steps: `<p>V = RNE ÷ TGA = ${R.money(rne)} ÷ ${R.num(tga, 2)} % = <b>${R.money(rne / (tga / 100))}</b>.</p><p>Vérification : ${R.money(rne / (tga / 100))} × ${R.num(tga, 2)} % ≈ ${R.money(rne)}.</p>`,72 };73 },74 },75 {76 id: "rne", title: "Du RBP au RNE", ch: "11", url: "/seance/11/#s-11-2",77 gen(R) {78 const n = R.pick([4, 6, 8, 12]);79 const loyer = R.step(850, 1650, 25);80 const inocc = R.pick([3, 4, 5]);81 const autres = R.step(0, 6000, 500);82 const ratio = R.pick([36, 38, 40, 42, 44]);83 const rbp = n * loyer * 12;84 const rbe = rbp * (1 - inocc / 100) + autres;85 const dep = rbe * ratio / 100;86 const rne = rbe - dep;87 return {88 enonce: `Un immeuble de <b>${n} logements</b> loués <b>${R.money(loyer)}</b> par mois (loyer du marché). Inoccupation et mauvaises créances : <b>${inocc} % du RBP</b> ; revenus accessoires : <b>${R.money(autres)}</b> par an ; dépenses d’exploitation : <b>${ratio} % du RBE</b>. Quel est le <b>RNE</b> ?`,89 answer: rne, unit: "$", tol: 0.003,90 steps: `<p>RBP = ${n} × ${R.money(loyer)} × 12 = ${R.money(rbp)}.</p><p>RBE = ${R.money(rbp)} × (1 − ${inocc} %) + ${R.money(autres)} = ${R.money(rbe)}.</p><p>Dépenses = ${ratio} % × ${R.money(rbe)} = ${R.money(dep)}.</p><p>RNE = ${R.money(rbe)} − ${R.money(dep)} = <b>${R.money(rne)}</b>.</p>`,91 };92 },93 },94 {95 id: "tga-extraction", title: "Extraction du TGA", ch: "12", url: "/seance/12/#s-12-2",96 gen(R) {97 const prix = R.step(600000, 3200000, 10000);98 const tga = R.pick([4.8, 5.1, 5.4, 5.6, 5.9, 6.2, 6.5]);99 const rne = Math.round(prix * tga / 100 / 10) * 10;100 return {101 enonce: `Un immeuble comparable s’est vendu <b>${R.money(prix)}</b> ; son RNE reconstruit selon les conventions du sujet est de <b>${R.money(rne)}</b>. Quel <b>TGA</b> en extrayez-vous ? (en %, deux décimales)`,102 answer: rne / prix * 100, unit: "%", tol: 0.005,103 steps: `<p>TGA = RNE ÷ prix = ${R.money(rne)} ÷ ${R.money(prix)} = <b>${R.pct(rne / prix * 100)}</b>.</p><p>MRN implicite = 1 ÷ TGA ≈ ${R.num(prix / rne, 2)}.</p>`,104 };105 },106 },107 {108 id: "bande", title: "TGA par bande d’investissement", ch: "12", url: "/seance/12/#s-12-2",109 gen(R) {110 const m = R.pick([65, 70, 75, 80]);111 const i = R.pick([4.5, 5, 5.5, 6]);112 const re = R.pick([7, 8, 9, 10]);113 const im = i / 100 / 12;114 const rm = 12 * im / (1 - Math.pow(1 + im, -300)) * 100;115 const tga = m / 100 * rm + (1 - m / 100) * re;116 return {117 enonce: `Financement type du marché : ratio prêt/valeur de <b>${m} %</b>, taux hypothécaire de <b>${R.num(i, 2)} %</b> amorti sur <b>25 ans</b> (constante hypothécaire annuelle R<sub>m</sub> = ${R.pct(rm)}), rendement exigé sur l’équité de <b>${re} %</b>. Quel est le <b>TGA</b> par bande d’investissement ? (en %)`,118 answer: tga, unit: "%", tol: 0.01,119 steps: `<p>TGA = M × R<sub>m</sub> + (1 − M) × R<sub>e</sub> = ${m} % × ${R.pct(rm)} + ${100 - m} % × ${re} %</p><p>= ${R.pct(m / 100 * rm)} + ${R.pct((1 - m / 100) * re)} = <b>${R.pct(tga)}</b>.</p>`,120 };121 },122 },123 {124 id: "mrb", title: "Multiplicateur de revenu brut", ch: "12", url: "/seance/12/#s-12-5",125 gen(R) {126 const rbe = R.step(60000, 420000, 1000);127 const mrb = R.pick([8.5, 9, 9.5, 10, 10.5, 11]);128 return {129 enonce: `Les ventes récentes d’immeubles semblables affichent un MRB de <b>${R.num(mrb, 1)}</b>. Le sujet a un RBE de <b>${R.money(rbe)}</b>. Quelle <b>indication de valeur</b> le multiplicateur donne-t-il ?`,130 answer: rbe * mrb, unit: "$", tol: 0.003,131 steps: `<p>V = RBE × MRB = ${R.money(rbe)} × ${R.num(mrb, 1)} = <b>${R.money(rbe * mrb)}</b>.</p><p>Rappel : le MRB est un filtre rapide, aveugle aux dépenses ; il ne remplace pas la capitalisation du RNE.</p>`,132 };133 },134 },135 {136 id: "reversion", title: "Valeur de réversion (DCF)", ch: "12", url: "/seance/12/#s-12-3",137 gen(R) {138 const rne = R.step(90000, 400000, 1000);139 const tgaout = R.pick([5.5, 5.75, 6, 6.25, 6.5]);140 const frais = R.pick([2, 2.5, 3, 4]);141 const brute = rne / (tgaout / 100);142 return {143 enonce: `À la fin d’une détention de 5 ans, le RNE de l’<b>année 6</b> est projeté à <b>${R.money(rne)}</b>. TGA de sortie : <b>${R.num(tgaout, 2)} %</b> ; frais de vente : <b>${R.num(frais, 1)} %</b> de la valeur brute. Quelle est la <b>valeur de réversion nette</b> ?`,144 answer: brute * (1 - frais / 100), unit: "$", tol: 0.003,145 steps: `<p>Valeur brute = RNE<sub>6</sub> ÷ TGA<sub>sortie</sub> = ${R.money(rne)} ÷ ${R.num(tgaout, 2)} % = ${R.money(brute)}.</p><p>Frais de vente = ${R.num(frais, 1)} % × ${R.money(brute)} = ${R.money(brute * frais / 100)}.</p><p>Réversion nette = <b>${R.money(brute * (1 - frais / 100))}</b>.</p>`,146 };147 },148 },149 {150 id: "va", title: "Valeur présente d’un flux", ch: "12", url: "/seance/12/#s-12-3",151 gen(R) {152 const fv = R.step(100000, 2500000, 5000);153 const r = R.pick([6, 6.5, 7, 7.5, 8, 9]);154 const n = R.int(3, 10);155 const pv = fv / Math.pow(1 + r / 100, n);156 return {157 enonce: `Quelle est la <b>valeur présente</b> de <b>${R.money(fv)}</b> reçus dans <b>${n} ans</b>, actualisés à <b>${R.num(r, 1)} %</b> ?`,158 answer: pv, unit: "$", tol: 0.003,159 steps: `<p>PV = FV ÷ (1 + r)<sup>n</sup> = ${R.money(fv)} ÷ (1,${String(r * 10).padStart(3, "0")})<sup>${n}</sup> = ${R.money(fv)} ÷ ${R.num(Math.pow(1 + r / 100, n), 4)} = <b>${R.money(pv)}</b>.</p>`,160 };161 },162 },163 {164 id: "cout-agevie", title: "Méthode du coût — âge/vie modifiée", ch: "10", url: "/seance/10/#s-10-3",165 gen(R) {166 const cneuf = R.step(380000, 900000, 5000);167 const cur = R.step(5000, 30000, 500);168 const age = R.int(8, 35);169 const vie = R.pick([50, 55, 60, 65]);170 const terrain = R.step(90000, 260000, 5000);171 const inc = (cneuf - cur) * age / vie;172 const val = cneuf - cur - inc + terrain;173 return {174 enonce: `Coût de remplacement à neuf : <b>${R.money(cneuf)}</b> ; entretien différé (curable) : <b>${R.money(cur)}</b> ; âge effectif : <b>${age} ans</b> ; vie utile économique : <b>${vie} ans</b> ; valeur du terrain : <b>${R.money(terrain)}</b>. Aucune dépréciation fonctionnelle ni économique. Quelle est la <b>valeur</b> par la méthode du coût (âge/vie modifiée) ?`,175 answer: val, unit: "$", tol: 0.003,176 steps: `<p>Base résiduelle = ${R.money(cneuf)} − ${R.money(cur)} = ${R.money(cneuf - cur)}.</p><p>Physique incurable = ${R.money(cneuf - cur)} × ${age}/${vie} = ${R.money(inc)}.</p><p>Valeur dépréciée des améliorations = ${R.money(cneuf)} − ${R.money(cur)} − ${R.money(inc)} = ${R.money(cneuf - cur - inc)}.</p><p>V = ${R.money(cneuf - cur - inc)} + ${R.money(terrain)} = <b>${R.money(val)}</b>.</p>`,177 };178 },179 },180 {181 id: "reconciliation", title: "Réconciliation pondérée", ch: "14", url: "/seance/14/#s-14-6",182 gen(R) {183 const base = R.step(400000, 2000000, 10000);184 const vc = base, vk = base + R.step(-60000, 60000, 5000), vr = base + R.step(-50000, 50000, 5000);185 const w = R.pick([[50, 20, 30], [40, 15, 45], [60, 10, 30], [35, 25, 40], [45, 20, 35]]);186 const val = (vc * w[0] + vk * w[1] + vr * w[2]) / 100;187 return {188 enonce: `Indications : comparaison <b>${R.money(vc)}</b> (poids ${w[0]} %), coût <b>${R.money(vk)}</b> (poids ${w[1]} %), revenu <b>${R.money(vr)}</b> (poids ${w[2]} %). Quelle est la <b>valeur pondérée</b> (avant arrondi) ?`,189 answer: val, unit: "$", tol: 0.002,190 steps: `<p>V = ${R.money(vc)} × ${w[0]} % + ${R.money(vk)} × ${w[1]} % + ${R.money(vr)} × ${w[2]} %</p><p>= ${R.money(vc * w[0] / 100)} + ${R.money(vk * w[1] / 100)} + ${R.money(vr * w[2] / 100)} = <b>${R.money(val)}</b> (à arrondir au 5 000 $ : ${R.money(Math.round(val / 5000) * 5000)}).</p>`,191 };192 },193 },194];195