Grailleton commited on
Commit
da475f5
·
1 Parent(s): d87a9a9

Remove LFS tracking

Browse files
.gitattributes CHANGED
@@ -1 +0,0 @@
1
- *.pkl filter=lfs diff=lfs merge=lfs -text
 
 
.gitignore CHANGED
@@ -1,9 +1,16 @@
1
  venv/
2
  __pycache__/
3
- *.pkl
4
  data/
5
  .ipynb_checkpoints/
6
  outputs/
7
  *.pyc
8
  *.egg-info/
9
  .env
 
 
 
 
 
 
 
 
1
  venv/
2
  __pycache__/
3
+ #*.pkl
4
  data/
5
  .ipynb_checkpoints/
6
  outputs/
7
  *.pyc
8
  *.egg-info/
9
  .env
10
+ src/model_rf.pkl
11
+ src/model_multi.pkl
12
+ src/modeles_segment.pkl
13
+ src/label_encoder.pkl
14
+ src/features.pkl
15
+ src/label_encoder_multi.pkl
16
+ src/features_multi.pkl
.~lock.documentation_immo_predict_v2_v3.docx# DELETED
@@ -1 +0,0 @@
1
- ,DESKTOP-AUN3R3J/Elyas,,12.03.2026 21:10,file:///C:/Users/Elyas/AppData/Roaming/OfficeDocOpener/4;
 
 
notebooks/analyse_immo.ipynb CHANGED
The diff for this file is too large to render. See raw diff
 
requirement.txt ADDED
@@ -0,0 +1 @@
 
 
1
+
src/static/script.js CHANGED
@@ -12,7 +12,6 @@ function initThree() {
12
  const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 100);
13
  camera.position.z = 30;
14
 
15
- // Particules
16
  const count = 1200;
17
  const positions = new Float32Array(count * 3);
18
  const colors = new Float32Array(count * 3);
@@ -24,20 +23,11 @@ function initThree() {
24
 
25
  const r = Math.random();
26
  if (r < 0.5) {
27
- // Bleu
28
- colors[i * 3] = 0.23;
29
- colors[i * 3 + 1] = 0.51;
30
- colors[i * 3 + 2] = 0.96;
31
  } else if (r < 0.8) {
32
- // Cyan
33
- colors[i * 3] = 0.02;
34
- colors[i * 3 + 1] = 0.71;
35
- colors[i * 3 + 2] = 0.83;
36
  } else {
37
- // Blanc doux
38
- colors[i * 3] = 0.55;
39
- colors[i * 3 + 1] = 0.58;
40
- colors[i * 3 + 2] = 0.70;
41
  }
42
  }
43
 
@@ -46,33 +36,21 @@ function initThree() {
46
  geo.setAttribute('color', new THREE.BufferAttribute(colors, 3));
47
 
48
  const mat = new THREE.PointsMaterial({
49
- size: 0.12,
50
- vertexColors: true,
51
- transparent: true,
52
- opacity: 0.7,
53
- sizeAttenuation: true
54
  });
55
 
56
  const points = new THREE.Points(geo, mat);
57
  scene.add(points);
58
 
59
- // Lignes de grille en perspective
60
- const lineMat = new THREE.LineBasicMaterial({
61
- color: 0x1e3a5f,
62
- transparent: true,
63
- opacity: 0.15
64
- });
65
 
66
  for (let i = -5; i <= 5; i++) {
67
  const hGeo = new THREE.BufferGeometry().setFromPoints([
68
- new THREE.Vector3(-40, i * 8, -10),
69
- new THREE.Vector3(40, i * 8, -10)
70
  ]);
71
  scene.add(new THREE.Line(hGeo, lineMat));
72
-
73
  const vGeo = new THREE.BufferGeometry().setFromPoints([
74
- new THREE.Vector3(i * 8, -40, -10),
75
- new THREE.Vector3(i * 8, 40, -10)
76
  ]);
77
  scene.add(new THREE.Line(vGeo, lineMat));
78
  }
@@ -107,7 +85,6 @@ function animateCounters() {
107
  const target = parseInt(el.dataset.target);
108
  const duration = 1500;
109
  const start = performance.now();
110
-
111
  function update(now) {
112
  const progress = Math.min((now - start) / duration, 1);
113
  const ease = 1 - Math.pow(1 - progress, 3);
@@ -159,7 +136,6 @@ async function loadCommunes() {
159
  sel.innerHTML = communes.map(c => `<option value="${c}">${c}</option>`).join('');
160
  }
161
 
162
- // ── Prédiction ──
163
  async function predict() {
164
  const btn = document.getElementById('cta-btn');
165
  const label = document.getElementById('cta-label');
@@ -172,6 +148,26 @@ async function predict() {
172
  btn.disabled = true;
173
 
174
  try {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  const res = await fetch('/api/predict', {
176
  method: 'POST',
177
  headers: { 'Content-Type': 'application/json' },
@@ -181,24 +177,27 @@ async function predict() {
181
  nb_pieces: steppers.pieces,
182
  nb_lots: steppers.lots,
183
  surface_terrain: document.getElementById('terrain').value,
184
- commune: document.getElementById('commune').value,
185
- departement: document.getElementById('departement').value
 
 
 
186
  })
187
  });
188
 
189
  const data = await res.json();
190
 
191
- // Remplir les résultats
192
  document.getElementById('result-price').textContent = fmt(data.prix);
193
  document.getElementById('result-sub').textContent =
194
- selectedType + ' · ' + document.getElementById('commune').value + ' (' + document.getElementById('departement').value + ')';
 
 
195
  document.getElementById('r-bas').textContent = fmt(data.fourchette_bas);
196
  document.getElementById('r-haut').textContent = fmt(data.fourchette_haut);
197
  document.getElementById('r-m2').textContent = new Intl.NumberFormat('fr-FR').format(data.prix_m2) + ' €/m²';
198
  document.getElementById('r-precision').textContent = data.precision + '%';
199
- document.getElementById('r-segment').textContent = data.segment.replace(/_/g, ' ');
200
 
201
- // Afficher et animer
202
  const result = document.getElementById('result');
203
  result.style.display = 'block';
204
  setTimeout(() => {
 
12
  const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 100);
13
  camera.position.z = 30;
14
 
 
15
  const count = 1200;
16
  const positions = new Float32Array(count * 3);
17
  const colors = new Float32Array(count * 3);
 
23
 
24
  const r = Math.random();
25
  if (r < 0.5) {
26
+ colors[i * 3] = 0.23; colors[i * 3 + 1] = 0.51; colors[i * 3 + 2] = 0.96;
 
 
 
27
  } else if (r < 0.8) {
28
+ colors[i * 3] = 0.02; colors[i * 3 + 1] = 0.71; colors[i * 3 + 2] = 0.83;
 
 
 
29
  } else {
30
+ colors[i * 3] = 0.55; colors[i * 3 + 1] = 0.58; colors[i * 3 + 2] = 0.70;
 
 
 
31
  }
32
  }
33
 
 
36
  geo.setAttribute('color', new THREE.BufferAttribute(colors, 3));
37
 
38
  const mat = new THREE.PointsMaterial({
39
+ size: 0.12, vertexColors: true, transparent: true, opacity: 0.7, sizeAttenuation: true
 
 
 
 
40
  });
41
 
42
  const points = new THREE.Points(geo, mat);
43
  scene.add(points);
44
 
45
+ const lineMat = new THREE.LineBasicMaterial({ color: 0x1e3a5f, transparent: true, opacity: 0.15 });
 
 
 
 
 
46
 
47
  for (let i = -5; i <= 5; i++) {
48
  const hGeo = new THREE.BufferGeometry().setFromPoints([
49
+ new THREE.Vector3(-40, i * 8, -10), new THREE.Vector3(40, i * 8, -10)
 
50
  ]);
51
  scene.add(new THREE.Line(hGeo, lineMat));
 
52
  const vGeo = new THREE.BufferGeometry().setFromPoints([
53
+ new THREE.Vector3(i * 8, -40, -10), new THREE.Vector3(i * 8, 40, -10)
 
54
  ]);
55
  scene.add(new THREE.Line(vGeo, lineMat));
56
  }
 
85
  const target = parseInt(el.dataset.target);
86
  const duration = 1500;
87
  const start = performance.now();
 
88
  function update(now) {
89
  const progress = Math.min((now - start) / duration, 1);
90
  const ease = 1 - Math.pow(1 - progress, 3);
 
136
  sel.innerHTML = communes.map(c => `<option value="${c}">${c}</option>`).join('');
137
  }
138
 
 
139
  async function predict() {
140
  const btn = document.getElementById('cta-btn');
141
  const label = document.getElementById('cta-label');
 
148
  btn.disabled = true;
149
 
150
  try {
151
+ const commune = document.getElementById('commune').value;
152
+ const dept = document.getElementById('departement').value;
153
+
154
+ let latitude = 0, longitude = 0, code_postal = '00000';
155
+
156
+ try {
157
+ const adresse = `${commune} ${dept} France`;
158
+ const geoRes = await fetch(
159
+ `https://api-adresse.data.gouv.fr/search/?q=${encodeURIComponent(adresse)}&limit=1`
160
+ );
161
+ const geoData = await geoRes.json();
162
+ if (geoData.features && geoData.features.length > 0) {
163
+ longitude = geoData.features[0].geometry.coordinates[0];
164
+ latitude = geoData.features[0].geometry.coordinates[1];
165
+ code_postal = geoData.features[0].properties.postcode || '00000';
166
+ }
167
+ } catch (e) {
168
+ console.log('Géocodage échoué, fallback centroïde');
169
+ }
170
+
171
  const res = await fetch('/api/predict', {
172
  method: 'POST',
173
  headers: { 'Content-Type': 'application/json' },
 
177
  nb_pieces: steppers.pieces,
178
  nb_lots: steppers.lots,
179
  surface_terrain: document.getElementById('terrain').value,
180
+ commune: commune,
181
+ departement: dept,
182
+ latitude: latitude,
183
+ longitude: longitude,
184
+ code_postal: code_postal
185
  })
186
  });
187
 
188
  const data = await res.json();
189
 
 
190
  document.getElementById('result-price').textContent = fmt(data.prix);
191
  document.getElementById('result-sub').textContent =
192
+ selectedType + ' · ' + commune + ' (' + dept + ')' +
193
+ ' · ' + data.dist_centre_km + ' km du centre · ' +
194
+ new Intl.NumberFormat('fr-FR').format(data.revenu_median_zone) + '€ revenu médian';
195
  document.getElementById('r-bas').textContent = fmt(data.fourchette_bas);
196
  document.getElementById('r-haut').textContent = fmt(data.fourchette_haut);
197
  document.getElementById('r-m2').textContent = new Intl.NumberFormat('fr-FR').format(data.prix_m2) + ' €/m²';
198
  document.getElementById('r-precision').textContent = data.precision + '%';
199
+ document.getElementById('r-segment').textContent = data.segment;
200
 
 
201
  const result = document.getElementById('result');
202
  result.style.display = 'block';
203
  setTimeout(() => {