"""TutorSyntax v26: k-nearest neighbours classifier on fictional soil sensors.
Save beside fictional_soil_sensors.csv and run Python 3.
No third-party packages or personal data needed.
"""
import csv
from math import hypot
from pathlib import Path

with Path(__file__).with_name('fictional_soil_sensors.csv').open(newline='', encoding='utf-8') as f:
    data = [{"id":r['id'], "temp":float(r['temperature_c']), "moisture":float(r['soil_moisture_percent']), "label":int(r['needs_water'])} for r in csv.DictReader(f)]
train, test = data[:12], data[12:]

def predict(record, k):
    nearest = sorted(train, key=lambda r:hypot((r['temp']-record['temp'])/20,
                                                    (r['moisture']-record['moisture'])/100))[:k]
    return int(sum(r['label'] for r in nearest) > k/2)

for k in (1, 3, 5):
    tp=tn=fp=fn=0
    for record in test:
        p=predict(record, k)
        a=record['label']
        if a==1 and p==1: tp+=1
        elif a==0 and p==0: tn+=1
        elif a==0 and p==1: fp+=1
        else: fn+=1
    precision = tp/(tp+fp) if tp+fp else None
    recall = tp/(tp+fn) if tp+fn else None
    print(f'k={k} | accuracy={(tp+tn)/len(test):.3f} | precision={precision} | recall={recall} | TP={tp} TN={tn} FP={fp} FN={fn}')
print('Caution: the training and test samples are tiny and entirely fictional.')
