2023-11-06 19:24:03
"""
Comment ça marche ?
Votre dossier doit contenir :
    - gen.py (ce fichier)
    - gold.png, silver.png, bronze.png
    - FUT-FONT.otf
    - logo-Ligue.png
    - flags/ contenant les drapeaux des pays
    - teams/ contenant les logos des équipes
    - pp/ contenant initialement les pps des joueurs souhaitant quelque chose d'autre
    que leur avatar geoguessr (par exemple leur pp discord)
    - cards/ ou seront produites les cartes
    - GUT cards data - stats.csv le fichier contenant toutes les stats
 
Le csv doit être sauvegardé avec ';' uniquement comme délimiteur de colonne.
Dans la colonne user_id à droite de pays, mettre l'user_id si le joueur souhaite avoir
son pin geoguessr comme pp, other si un autre fichier standard (type pp discord) est
fourni, blank si on veut créer une carte sans pp (par exemple si on veut mettre une
pp avec transparence après coup).
 
Une fois ceci préparé, il n'y a plus qu'à exécuter le programme avec la commande
python gen.py a b
si vous voulez générer les cartes pour les joueurs entre les lignes a et b (incluses)
 
Si il y a une erreur, c'est probablement du à une des causes suivantes :
    - nom du fichier du logo d'équipe n'étant pas exactement le même que dans le tableur
    - nom du fichier de la pp n'étant pas le même que le pseudo du tableur
    - fichier défaillant (à cause de la transparence notamment)
"""
 
 
import csv
from PIL import Image, ImageFont, ImageDraw, ImageOps
import os, sys
import requests
 
cwd = os.path.abspath(os.getcwd()) + "/"
path_data = cwd + "GUT cards data - stats.csv"
 
beg, end = int(sys.argv[1])-1, int(sys.argv[2])
 
data = open(path_data, newline='')
rows = list(csv.reader(data, delimiter=';', quotechar='|'))
 
font = ImageFont.truetype(cwd + "FUT-FONT.otf",50)
font_name = ImageFont.truetype(cwd + "FUT-FONT.otf",62)
font_gen = ImageFont.truetype(cwd + "FUT-FONT.otf",80)
 
headers = {"Content-Type": "application/json",
           "cookie": "_ncfa=56WV0YCiQCwUIvchHn44imbFPUuEkPFmwzICJJSSzcw=Lt5q7OIEYXeGWKSfPVV0XG3fpHYXcd1k8tpz6mpGbnDp9xKXiL4rqWnyj1JbsIZejcGnvzZACpa58FpdGLrGi8jD4SPoQgWc8SiK9zNO8Tk="}
 
def get_image_via_user_id(user_id, path_pp):
    res_temp = requests.get(f"https://www.geoguessr.com/api/v3/users/{user_id}",headers=headers).json()
    r = requests.get(f"https://www.geoguessr.com/images/plain/{res_temp['pin']['url']}",headers=headers)
 
    with open(path_pp, 'wb') as f:
        for chunk in r:
            f.write(chunk)
 
metal = ["bronze","silver","gold"]
 
ligue_logo = Image.open(cwd+"logo-Ligue.png")
h_ligue = 46
ligue_logo = ligue_logo.resize((h_ligue,h_ligue))
 
for row in rows[beg:end]:
    pseudo = row[0]
    move, nm, info, meta, spe, acc, gen, team, country = int(row[53]), int(row[54]), int(row[55]), int(row[56]), int(row[57]), int(row[58]), int(row[59]), row[60], row[62]
    div = 0 if gen<70 else 1 if gen<80 else 2
 
    card = Image.open(cwd+metal[div]+".png")
    draw = ImageDraw.Draw(card)
 
    #Writing pseudo
    draw.text((250,410), pseudo.upper(), font=font_name, anchor="mm", fill="black", stroke_fill="black", stroke_width=1)
 
    xl, xr = 100, 150
    yl, yd = 460, 55
 
    #Writing stats
    draw.text((xl,yl), str(move), font=font, anchor="lt", fill="black", stroke_fill="black", stroke_width=1)
    draw.text((xr,yl), "MOVE", font=font, anchor="lt", fill="black")
 
    draw.text((xl,yl+yd), str(nm), font=font, anchor="lt", fill="black", stroke_fill="black", stroke_width=1)
    draw.text((xr,yl+yd), "NM", font=font, anchor="lt", fill="black")
 
    draw.text((xl,yl+2*yd), str(info), font=font, anchor="lt", fill="black", stroke_fill="black", stroke_width=1)
    draw.text((xr,yl+2*yd), "INFO", font=font, anchor="lt", fill="black")
 
    xl, xr = 270, 270 + 50
 
    draw.text((xl,yl), str(meta), font=font, anchor="lt", fill="black", stroke_fill="black", stroke_width=1)
    draw.text((xr,yl), "META", font=font, anchor="lt", fill="black")
 
    draw.text((xl,yl+yd), str(spe), font=font, anchor="lt", fill="black", stroke_fill="black", stroke_width=1)
    draw.text((xr,yl+yd), "SPE", font=font, anchor="lt", fill="black")
 
    draw.text((xl,yl+2*yd), str(acc), font=font, anchor="lt", fill="black", stroke_fill="black", stroke_width=1)
    draw.text((xr,yl+2*yd), "ACC", font=font, anchor="lt", fill="black")
 
    x, y = 133, 162
    draw.text((x,y), str(gen), font=font_gen, anchor="mm", fill="black", stroke_fill="black", stroke_width=2)
 
    #Ligue logo
    box = (250-h_ligue//2, 645-h_ligue//2, 250+h_ligue//2, 645+h_ligue//2)
    card.paste(ligue_logo, box, ligue_logo)
 
    #Team logo
    x, y = 133, 325
    h = 40
    logo = Image.open(cwd+"teams/"+team+".png")
    logo = ImageOps.pad(logo, (2*40, 2*40))
    box = (x-h, y-h, x+h, y+h)
    card.paste(logo, box, logo)
 
    #Country flag
    y = 243
    h = 26
    flag = Image.open(cwd+"flags/"+country+".png")
    cw, ch = flag.size
    ratio = ch//(2*h)
    w = (cw//2)//ratio
    flag = flag.resize((2*w,2*h))
    w, h = flag.size
    h//=2
    w//=2
    box = (x-w, y-h, x+w, y+h)
    card.paste(flag, box) 
 
    #Profile pic, to improve
    avatar_size = 280
    x, y = 330, 260
    user_id = row[63]
    if user_id != "blank":
        path_pp = cwd+"pp/"+pseudo+".png"
 
        if not os.path.exists(path_pp):
            get_image_via_user_id(user_id, path_pp)
 
        avatar = Image.open(path_pp)
        avatar = avatar.resize((avatar_size, avatar_size))
        mask_im = Image.new("L", avatar.size, 0)
        draw = ImageDraw.Draw(mask_im)
        draw.ellipse((0, 0, avatar_size, avatar_size), fill=255)
        draw.rectangle([0, 252, avatar_size, avatar_size], fill=0)
        draw.rectangle([274, 0, avatar_size, avatar_size], fill=0)
        mask_im.save('mask_circle.jpg', quality=95)
        card.paste(avatar, (x-avatar_size//2, y-avatar_size//2, x+avatar_size//2, y+avatar_size//2), mask_im)
 
    card.save(cwd+"cards/"+pseudo+".png")
Invalid Email or Password