Separe jogos adequados de jogos similares

PythonBeginner
Pratique Agora

Introdução

Uma pequena biblioteca de jogos precisa de alternativas para esta noite. Um jogo pode parecer com seu favorito e ainda estar indisponível ou não comportar o grupo. Você separará duas perguntas: quais jogos podem ser usados e como comparar suas características numéricas.

Você criará um programa de adequação reproduzível e um resultado JSON real. São necessários funções e dicionários básicos de Python, arrays introdutórios do NumPy e leitura de tabelas. Conhecer classificação por vizinhos mais próximos ajuda, mas não há rótulos a prever. Python e NumPy estão prontos; scikit-learn não é necessário. Os 45 minutos são uma estimativa do autor, incluindo leitura e correções comuns.

Decida quais jogos podem ser usados hoje

Nesta etapa, você inspecionará o catálogo real da biblioteca e implementará as regras de adequação desta noite em uma região de uma função preparada.

Abra a aba Terminal. Todos os comandos são executados nela, incluindo o leitor de arquivos salvos. Abrir ou reconectar Terminal não reinstala nem reinicia seu espaço de trabalho. cd muda o diretório atual deste terminal; outro terminal tem seu próprio diretório.

cd /home/labex/project/board-games

Comece com a entrada real. CSV tem um cabeçalho seguido por linhas separadas por vírgulas. cat imprime o arquivo sem alterá-lo. Este é o catálogo completo, sem filtros, não uma lista de jogos já qualificados para esta noite.

cat catalog.csv

Cada linha representa uma edição distinta de jogo. Seu game_id único e não vazio é a chave usada para encontrar e associar essa edição. title é texto de exibição: várias edições Harbor têm IDs diferentes e devem permanecer separadas. minutes é uma estimativa positiva de duração; complexity é uma avaliação sintética de 1 a 5, com valores maiores indicando maior complexidade. Os inteiros min_players e max_players incluem ambas as pontas. A entrada sintética está completa e tem uma linha por ID; limpar dados malformados está fora deste exercício.

cat availability.csv

A tabela separada de empréstimos tem uma linha para cada ID do catálogo, em outra ordem. Seu texto CSV true/false torna-se booleanos Python True/False no carregador preparado. Relacionar por chave significa encontrar o mesmo game_id, não anexar a linha 1 à linha 1. Chaves únicas e uma linha de estado de empréstimo por ID evitam correspondências ambíguas ou ausentes. Você implementará essa busca.

JSON armazena valores nomeados, listas e objetos. Leia a solicitação desta noite:

cat night.json

reference_id é o exemplo a que se deseja assemelhar, players é o tamanho do grupo e k é a quantidade solicitada de alternativas próximas, usada no próximo laboratório. A referência é um exemplo de consulta e pode estar indisponível ou ser inadequada; somente as alternativas retornadas precisam atender à noite. Exclua apenas seu ID exato, não todos os jogos com o mesmo título ou características idênticas. A visão geral da entrada bruta não aplicou essas regras nem gerou um resultado de adequação.

Considere três jogos disponíveis para quatro pessoas: Harbor tem 60 minutos e complexidade 3, Quay tem 61 e 5, e Bridge tem 90 e 3. Diferenças nas unidades originais são candidato menos referência: Quay é um minuto mais longo e dois pontos mais complexo; Bridge é trinta minutos mais longo e igualmente complexo. O -c do Python executa o cálculo entre aspas como um argumento. O ponto e vírgula separa duas instruções Python.

python3 -c "print('Quay minutes:', 61 - 60); print('Bridge minutes:', 90 - 60)"

Espere 1 e 30. A distância euclidiana bruta eleva ao quadrado e soma as diferenças de características e depois extrai a raiz quadrada. Trinta minutos podem dominar dois pontos de complexidade se essas unidades forem misturadas diretamente. Você definirá uma escala comum a seguir; primeiro decida quem pode competir.

Você pode editar suitability.py, ranking.py, seus arquivos de resultados e seus próprios backups dos scripts. Preserve todas as entradas CSV/JSON fornecidas, planner.py, coursekit.py, show_results.py e ambas as cópias de recuperação starter-*.py. planner.py seleciona uma função pública e delega leitura de arquivos, conversão de tipos e gravação JSON a coursekit.py; nenhum dos dois toma a decisão de negócio. Deixe ranking.py incompleto neste laboratório.

Leia o módulo preparado:

cat suitability.py

choose_games(catalog, availability, request) recebe as listas carregadas de dicionários e o dicionário da solicitação. Suas duas regiões identificadas começam com eligible = [] e scale = {}. São espaços reservados incompletos, não uma afirmação de que nenhum jogo se qualifica. O retorno final reúne os IDs e a escala para o executor. Você substituirá a região de adequação agora e manterá o espaço reservado da escala para a etapa 2. A preparação e a visão geral da entrada não criam resultado avaliado.

Faça um backup deste módulo. cp SOURCE DESTINATION copia apenas o arquivo nomeado; .bak é um sufixo de backup. Não sobrescreva esse backup após um erro.

cp suitability.py suitability.py.bak

nano edita um arquivo existente dentro de Terminal. O LC_ALL=C.UTF-8 local ao comando seleciona UTF-8 apenas para este editor, sem alterar configurações globais do shell. Na faixa de atalhos do nano, ^ significa manter Ctrl pressionado. As setas movem o cursor; digitar insere texto. Ctrl+W, uma frase de busca e Enter localizam texto. Home vai ao início da linha; Ctrl+K recorta essa linha inteira. Python usa indentação: as linhas abaixo começam com quatro espaços dentro da função, com mais recuo dentro do laço e da condição.

LC_ALL=C.UTF-8 nano suitability.py

Primeiro pratique descartar uma edição indesejada. Encontre ## Candidate identities com Ctrl+W e Enter, pressione End e acrescente temporary ao comentário. Pressione Ctrl+X e N na pergunta sobre salvar. Você sai sem alterar o arquivo. Abra-o novamente:

LC_ALL=C.UTF-8 nano suitability.py

Encontre eligible = [], pressione Home e Ctrl+K uma vez para remover apenas essa linha provisória. Mantenha o cabeçalho da função, a região de escala e o retorno final. Insira ali as linhas recuadas a seguir. A compreensão de dicionário constrói uma busca de ID para disponibilidade. O laço usa and para três exigências independentes; comparações encadeadas <= incluem ambos os limites de jogadores. append acrescenta o ID correspondente, não o título de exibição.

    status = {row['game_id']: row['available'] for row in availability}
    eligible = []
    for game in catalog:
        different_id = game['game_id'] != request['reference_id']
        fits_group = game['min_players'] <= request['players'] <= game['max_players']
        if different_id and fits_group and status[game['game_id']]:
            eligible.append(game['game_id'])

Salve com Ctrl+O, pressione Enter para confirmar o nome inalterado e Ctrl+X para sair. Salvar não executa a função. Seu retorno existente usa sorted(eligible) para produzir uma lista alfabética de identidades, independentemente da ordem das linhas de entrada, e deixa scale como objeto vazio.

O --mode suitable do executor seleciona choose_games; o --output suitable.json obrigatório nomeia seu resultado salvo. Os padrões são catalog.csv, availability.csv e night.json neste diretório. --catalog, --availability e --request podem selecionar outros caminhos. Essas entradas continuam somente leitura.

python3 planner.py --mode suitable --output suitable.json

O leitor fornecido abre somente esse JSON salvo. Não gera um arquivo ausente nem calcula nada a partir do catálogo.

python3 show_results.py suitable.json

Espere Scale: {} e IDs left, near, raw, right, same, zero. Tanto same quanto zero são outras edições Harbor; zero tem até características numéricas idênticas às da referência. blocked está indisponível, small não comporta quatro e ref é a referência exata. Compare essas identidades com as duas tabelas de entrada. A qualificação agora está completa, mas a escala ainda está deliberadamente sem implementação.

A próxima falha de diretório incorreto é intencional. Suba um diretório:

cd /home/labex/project
python3 planner.py --mode suitable --output suitable.json

Python informa can't open file e No such file or directory: não encontra o executor aqui. Seu programa e resultado existentes não foram reiniciados. pwd revela o diretório deste terminal; volte ao espaço de trabalho e execute novamente o comando real.

pwd
cd /home/labex/project/board-games
python3 planner.py --mode suitable --output suitable.json
python3 show_results.py suitable.json

Para um erro de edição, leia o nome do arquivo e o número da linha do Python, reabra o módulo no nano e corrija apenas a região afetada. Um SyntaxError geralmente aponta para dois-pontos ou aspas ausentes; um IndentationError significa que os espaços iniciais precisam de atenção. Salve, saia e execute novamente. Ctrl+X, N abandona alterações não salvas. Se necessário, cp suitability.py.bak suitability.py restaura apenas esta base incompleta, portanto você deverá reaplicar a região de adequação depois. Nem um backup nem o starter-suitability.py protegido é sua solução concluída. Não execute a preparação novamente nem altere entradas para recuperar.

Mantenha uma escala para o catálogo inteiro

Nesta etapa, você implementará a região de escala preservando sua lógica de adequação concluída.

Continue na aba Terminal. Declare o diretório explicitamente para funcionar também em outro terminal.

cd /home/labex/project/board-games

Uma característica é uma propriedade numérica usada na comparação. A ordem é sempre minutes, depois complexity; disponibilidade e limites de participantes definem adequação, não distância. Encontre mínimo e máximo no catálogo inteiro, incluindo referência, jogos indisponíveis e inadequados. A amplitude é máximo menos mínimo. MinMax converte x em (x - minimum) / range: as diferenças passam a representar frações das amplitudes correspondentes.

Os mínimos completos são [10, 1] e amplitudes [100, 4]. Quay vira [1/100, 2/4], Bridge [30/100, 0/4]. A distância escalada de Quay é aproximadamente 0.5001, a de Bridge 0.3. A métrica muda a ordem, mas nenhuma unidade revela preferências pessoais. Pesos iguais após a escala são uma escolha explícita deste exercício.

O catálogo serve para definir a métrica, não como treino supervisionado. Sem rótulo futuro, não há divisão treino/teste. Alterar apenas disponibilidade não pode mudar escala nem distâncias dos candidatos restantes. Ajustar parâmetros depois de filtrar moveria a régua a cada empréstimo.

Uma característica constante tem amplitude zero. Salve o valor real 0, mas use divisor 1 na distância posterior. Como a referência pertence ao catálogo, todas as diferenças nessa característica são zero e não contribuem para a distância. Isso evita divisão por zero sem inventar informação.

Mantenha um novo backup da sua fase funcional de adequação, deixando intacto o backup da base original:

cp suitability.py suitability-ids.py.bak
LC_ALL=C.UTF-8 nano suitability.py

Encontre scale = {} com Ctrl+W e Enter, pressione Home e recorte apenas essa linha provisória com Ctrl+K. Deixe inalterados a busca de IDs e o laço concluídos acima dela. Insira as quatro linhas recuadas abaixo. np.array constrói uma tabela numérica de duas colunas na ordem publicada das características; axis=0 encontra mínimos e máximos ao longo de cada coluna. tolist() converte arrays em listas comuns que JSON pode salvar.

    features = np.array([[game['minutes'], game['complexity']] for game in catalog])
    minimum = features.min(axis=0)
    ranges = features.max(axis=0) - minimum
    scale = {'min': minimum.tolist(), 'range': ranges.tolist()}

O retorno existente agora inclui esta scale calculada e seus mesmos IDs ordenados. Salve com Ctrl+O, Enter e Ctrl+X. Você acrescentou uma região em vez de substituir o trabalho anterior ou anexar outro programa.

O resultado exige cada ID elegível uma vez, alfabeticamente. Guarde números, não strings formatadas. scale.min e scale.range têm dois números na ordem indicada. Campos explicativos adicionais inofensivos são permitidos. As tolerâncias absoluta e relativa são 1e-8: admitem variações normais de ponto flutuante, não outra métrica.

Gere novamente o resultado real usando as entradas originais e substitua apenas sua saída.

python3 planner.py --mode suitable --output suitable.json
python3 show_results.py suitable.json

Espere mínimos 10 e 1, amplitudes 100 e 4 e os mesmos seis IDs elegíveis. O leitor pode mostrar 10.0 em vez de 10; ambos são o número dez. Inspecione diretamente a estrutura salva:

cat suitable.json

Se uma edição danificar a região de adequação, cp suitability-ids.py.bak suitability.py restaura apenas essa fase funcional. Reabra o nano e implemente novamente a região de escala. Já cp starter-suitability.py suitability.py restaura a base incompleta e perde ambas as regiões; use somente ao recomeçar intencionalmente. Correções comuns devem reparar as linhas relevantes, salvar, sair e executar novamente. Preserve ambos os arquivos iniciais fornecidos e todas as entradas. Reconectar Terminal nunca executa a preparação nem restaura um backup por você.

Autoverificação: a adequação desta noite pode mudar sem alterar esta régua do catálogo inteiro. No próximo laboratório independente, a função completa de adequação é fornecida para você se concentrar em distâncias e seleção.

Resumo

Você separou adequação e similaridade, relacionou registros independentes por IDs estáveis, preservou alternativas legítimas de mesmo título ou diferença zero e definiu uma escala MinMax fixa usando o catálogo inteiro. suitable.json é um resultado real que pode ser regenerado. O próximo laboratório usa esse conhecimento para medir e explicar candidatos, mas começa em um ambiente independente.