tormenta20 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +27 -0
- data/README.md +203 -12
- data/Rakefile +9 -0
- data/db/schema.sql +382 -0
- data/db/seeds.rb +377 -0
- data/db/tormenta20.sqlite3 +0 -0
- data/docs/armaduras.md +72 -0
- data/docs/armas.md +95 -0
- data/docs/classes.md +105 -0
- data/docs/divindades.md +77 -0
- data/docs/escudos.md +49 -0
- data/docs/itens.md +59 -0
- data/docs/magias.md +157 -0
- data/docs/materiais_especiais.md +50 -0
- data/docs/melhorias.md +55 -0
- data/docs/origens.md +61 -0
- data/docs/poderes.md +98 -0
- data/docs/regras.md +51 -0
- data/examples/database_usage.rb +155 -0
- data/src/json/classes/arcanista.json +86 -0
- data/src/json/classes/barbaro.json +85 -0
- data/src/json/classes/bardo.json +91 -0
- data/src/json/classes/bucaneiro.json +96 -0
- data/src/json/classes/cacador.json +96 -0
- data/src/json/classes/cavaleiro.json +87 -0
- data/src/json/classes/clerigo.json +82 -0
- data/src/json/classes/druida.json +88 -0
- data/src/json/classes/guerreiro.json +90 -0
- data/src/json/classes/inventor.json +100 -0
- data/src/json/classes/ladino.json +96 -0
- data/src/json/classes/lutador.json +90 -0
- data/src/json/classes/nobre.json +100 -0
- data/src/json/classes/paladino.json +93 -0
- data/src/json/deuses/aharadak.json +26 -0
- data/src/json/deuses/allihanna.json +26 -0
- data/src/json/deuses/arsenal.json +28 -0
- data/src/json/deuses/azgher.json +28 -0
- data/src/json/deuses/hyninn.json +28 -0
- data/src/json/deuses/kallyadranoch.json +28 -0
- data/src/json/deuses/khalmyr.json +27 -0
- data/src/json/deuses/lena.json +28 -0
- data/src/json/deuses/lin_wu.json +28 -0
- data/src/json/deuses/marah.json +28 -0
- data/src/json/deuses/megalokk.json +28 -0
- data/src/json/deuses/nimb.json +27 -0
- data/src/json/deuses/oceano.json +26 -0
- data/src/json/deuses/sszzaas.json +28 -0
- data/src/json/deuses/tanna_toh.json +28 -0
- data/src/json/deuses/tenebra.json +26 -0
- data/src/json/deuses/thwor.json +27 -0
- data/src/json/deuses/thyatis.json +26 -0
- data/src/json/deuses/valkaria.json +30 -0
- data/src/json/deuses/wynna.json +25 -0
- data/src/json/equipamentos/armaduras/leves/armadura_acolchoada.json +15 -0
- data/src/json/equipamentos/armaduras/leves/armadura_de_couro.json +13 -0
- data/src/json/equipamentos/armaduras/leves/couraca.json +13 -0
- data/src/json/equipamentos/armaduras/leves/couro_batido.json +13 -0
- data/src/json/equipamentos/armaduras/leves/gibao_de_peles.json +13 -0
- data/src/json/equipamentos/armaduras/pesadas/armadura_completa.json +19 -0
- data/src/json/equipamentos/armaduras/pesadas/brunea.json +17 -0
- data/src/json/equipamentos/armaduras/pesadas/cota_de_malha.json +17 -0
- data/src/json/equipamentos/armaduras/pesadas/loriga_segmentada.json +17 -0
- data/src/json/equipamentos/armaduras/pesadas/meia_armadura.json +17 -0
- data/src/json/equipamentos/armas/exoticas/chicote.json +23 -0
- data/src/json/equipamentos/armas/exoticas/corrente_de_espinhos.json +23 -0
- data/src/json/equipamentos/armas/exoticas/espada_bastarda.json +19 -0
- data/src/json/equipamentos/armas/exoticas/katana.json +19 -0
- data/src/json/equipamentos/armas/exoticas/machado_anao.json +19 -0
- data/src/json/equipamentos/armas/exoticas/machado_taurico.json +17 -0
- data/src/json/equipamentos/armas/exoticas/rede.json +41 -0
- data/src/json/equipamentos/armas/fogo/mosquete.json +21 -0
- data/src/json/equipamentos/armas/fogo/pistola.json +21 -0
- data/src/json/equipamentos/armas/marciais/alabarda.json +17 -0
- data/src/json/equipamentos/armas/marciais/alfange.json +17 -0
- data/src/json/equipamentos/armas/marciais/arco_longo.json +22 -0
- data/src/json/equipamentos/armas/marciais/besta_pesada.json +21 -0
- data/src/json/equipamentos/armas/marciais/cimitarra.json +17 -0
- data/src/json/equipamentos/armas/marciais/espada_longa.json +17 -0
- data/src/json/equipamentos/armas/marciais/florete.json +17 -0
- data/src/json/equipamentos/armas/marciais/gadanho.json +17 -0
- data/src/json/equipamentos/armas/marciais/lanca_montada.json +20 -0
- data/src/json/equipamentos/armas/marciais/machadinha.json +19 -0
- data/src/json/equipamentos/armas/marciais/machado_de_batalha.json +17 -0
- data/src/json/equipamentos/armas/marciais/machado_de_guerra.json +17 -0
- data/src/json/equipamentos/armas/marciais/mangual.json +21 -0
- data/src/json/equipamentos/armas/marciais/marreta.json +17 -0
- data/src/json/equipamentos/armas/marciais/martelo_de_guerra.json +17 -0
- data/src/json/equipamentos/armas/marciais/montante.json +17 -0
- data/src/json/equipamentos/armas/marciais/picareta.json +17 -0
- data/src/json/equipamentos/armas/marciais/tridente.json +22 -0
- data/src/json/equipamentos/armas/simples/adaga.json +21 -0
- data/src/json/equipamentos/armas/simples/arco_curto.json +21 -0
- data/src/json/equipamentos/armas/simples/azagaia.json +20 -0
- data/src/json/equipamentos/armas/simples/besta_leve.json +21 -0
- data/src/json/equipamentos/armas/simples/bordao.json +17 -0
- data/src/json/equipamentos/armas/simples/clava.json +17 -0
- data/src/json/equipamentos/armas/simples/espada_curta.json +17 -0
- data/src/json/equipamentos/armas/simples/foice.json +17 -0
- data/src/json/equipamentos/armas/simples/funda.json +23 -0
- data/src/json/equipamentos/armas/simples/lanca.json +19 -0
- data/src/json/equipamentos/armas/simples/maca.json +17 -0
- data/src/json/equipamentos/armas/simples/pique.json +17 -0
- data/src/json/equipamentos/armas/simples/tacape.json +17 -0
- data/src/json/equipamentos/escudos/escudo_leve.json +22 -0
- data/src/json/equipamentos/escudos/escudo_pesado.json +22 -0
- data/src/json/equipamentos/itens/alimentacao/batata_valkariana.json +14 -0
- data/src/json/equipamentos/itens/alimentacao/gorad_quente.json +12 -0
- data/src/json/equipamentos/itens/alimentacao/macarrao_de_yuvalin.json +12 -0
- data/src/json/equipamentos/itens/alimentacao/prato_do_aventureiro.json +13 -0
- data/src/json/equipamentos/itens/alimentacao/racao_de_viagem.json +14 -0
- data/src/json/equipamentos/itens/alimentacao/refeicao_comum.json +9 -0
- data/src/json/equipamentos/itens/alimentacao/sopa_de_peixe.json +13 -0
- data/src/json/equipamentos/itens/alquimicos/catalisadores/baga_de_fogo.json +17 -0
- data/src/json/equipamentos/itens/alquimicos/catalisadores/dente_de_dragao.json +17 -0
- data/src/json/equipamentos/itens/alquimicos/catalisadores/essencia_abissal.json +22 -0
- data/src/json/equipamentos/itens/alquimicos/catalisadores/liquen_lilas.json +18 -0
- data/src/json/equipamentos/itens/alquimicos/catalisadores/musgo_purpura.json +18 -0
- data/src/json/equipamentos/itens/alquimicos/catalisadores/ossos_de_monstro.json +17 -0
- data/src/json/equipamentos/itens/alquimicos/catalisadores/po_de_cristal.json +18 -0
- data/src/json/equipamentos/itens/alquimicos/catalisadores/po_de_giz.json +18 -0
- data/src/json/equipamentos/itens/alquimicos/catalisadores/ramo_verdejante.json +16 -0
- data/src/json/equipamentos/itens/alquimicos/catalisadores/saco_de_sal.json +18 -0
- data/src/json/equipamentos/itens/alquimicos/catalisadores/seixo_de_ambar.json +18 -0
- data/src/json/equipamentos/itens/alquimicos/catalisadores/terra_de_cemiterio.json +18 -0
- data/src/json/equipamentos/itens/alquimicos/preparados/acido.json +19 -0
- data/src/json/equipamentos/itens/alquimicos/preparados/balsamo_restaurador.json +16 -0
- data/src/json/equipamentos/itens/alquimicos/preparados/bomba.json +30 -0
- data/src/json/equipamentos/itens/alquimicos/preparados/cosmetico.json +18 -0
- data/src/json/equipamentos/itens/alquimicos/preparados/elixir_do_amor.json +23 -0
- data/src/json/equipamentos/itens/alquimicos/preparados/essencia_de_mana.json +16 -0
- data/src/json/equipamentos/itens/alquimicos/preparados/fogo_alquimico.json +27 -0
- data/src/json/equipamentos/itens/alquimicos/preparados/po_do_desaparecimento.json +18 -0
- data/src/json/equipamentos/itens/alquimicos/venenos/beladona.json +22 -0
- data/src/json/equipamentos/itens/alquimicos/venenos/bruma_sonolenta.json +21 -0
- data/src/json/equipamentos/itens/alquimicos/venenos/cicuta.json +22 -0
- data/src/json/equipamentos/itens/alquimicos/venenos/essencia_de_sombra.json +20 -0
- data/src/json/equipamentos/itens/alquimicos/venenos/nevoa_toxica.json +22 -0
- data/src/json/equipamentos/itens/alquimicos/venenos/peconha_comum.json +24 -0
- data/src/json/equipamentos/itens/alquimicos/venenos/peconha_concentrada.json +22 -0
- data/src/json/equipamentos/itens/alquimicos/venenos/peconha_potente.json +22 -0
- data/src/json/equipamentos/itens/alquimicos/venenos/po_de_lich.json +23 -0
- data/src/json/equipamentos/itens/alquimicos/venenos/riso_de_nimb.json +21 -0
- data/src/json/equipamentos/itens/animais/alforje.json +11 -0
- data/src/json/equipamentos/itens/animais/cao_de_caca.json +18 -0
- data/src/json/equipamentos/itens/animais/cavalo.json +20 -0
- data/src/json/equipamentos/itens/animais/cavalo_de_guerra.json +17 -0
- data/src/json/equipamentos/itens/animais/estabulo.json +10 -0
- data/src/json/equipamentos/itens/animais/ponei.json +21 -0
- data/src/json/equipamentos/itens/animais/ponei_de_guerra.json +18 -0
- data/src/json/equipamentos/itens/animais/trobo.json +14 -0
- data/src/json/equipamentos/itens/aventura/agua_benta.json +23 -0
- data/src/json/equipamentos/itens/aventura/algemas.json +35 -0
- data/src/json/equipamentos/itens/aventura/arpeu.json +18 -0
- data/src/json/equipamentos/itens/aventura/bandoleira_de_pocoes.json +15 -0
- data/src/json/equipamentos/itens/aventura/barraca.json +14 -0
- data/src/json/equipamentos/itens/aventura/corda.json +26 -0
- data/src/json/equipamentos/itens/aventura/espelho.json +10 -0
- data/src/json/equipamentos/itens/aventura/lampiao.json +19 -0
- data/src/json/equipamentos/itens/aventura/mochila.json +12 -0
- data/src/json/equipamentos/itens/aventura/mochila_de_aventureiro.json +14 -0
- data/src/json/equipamentos/itens/aventura/oleo.json +19 -0
- data/src/json/equipamentos/itens/aventura/organizador_de_pergaminhos.json +14 -0
- data/src/json/equipamentos/itens/aventura/pe_de_cabra.json +18 -0
- data/src/json/equipamentos/itens/aventura/saco_de_dormir.json +13 -0
- data/src/json/equipamentos/itens/aventura/simbolo_sagrado.json +15 -0
- data/src/json/equipamentos/itens/aventura/tocha.json +28 -0
- data/src/json/equipamentos/itens/aventura/vara_de_madeira.json +12 -0
- data/src/json/equipamentos/itens/esotericos/bolsa_de_po.json +17 -0
- data/src/json/equipamentos/itens/esotericos/cajado_arcano.json +20 -0
- data/src/json/equipamentos/itens/esotericos/cetro_elemental.json +22 -0
- data/src/json/equipamentos/itens/esotericos/costela_de_lich.json +18 -0
- data/src/json/equipamentos/itens/esotericos/dedo_de_ente.json +21 -0
- data/src/json/equipamentos/itens/esotericos/luva_de_ferro.json +17 -0
- data/src/json/equipamentos/itens/esotericos/medalhao_de_prata.json +16 -0
- data/src/json/equipamentos/itens/esotericos/orbe_cristalino.json +15 -0
- data/src/json/equipamentos/itens/esotericos/tomo_hermetico.json +17 -0
- data/src/json/equipamentos/itens/esotericos/varinha_arcana.json +15 -0
- data/src/json/equipamentos/itens/ferramentas/alaude_elfico.json +16 -0
- data/src/json/equipamentos/itens/ferramentas/colecao_de_livros.json +16 -0
- data/src/json/equipamentos/itens/ferramentas/equipamento_de_viagem.json +19 -0
- data/src/json/equipamentos/itens/ferramentas/estojo_de_disfarces.json +18 -0
- data/src/json/equipamentos/itens/ferramentas/flauta_mistica.json +17 -0
- data/src/json/equipamentos/itens/ferramentas/gazua.json +18 -0
- data/src/json/equipamentos/itens/ferramentas/instrumento_musical.json +20 -0
- data/src/json/equipamentos/itens/ferramentas/instrumentos_de_oficio.json +21 -0
- data/src/json/equipamentos/itens/ferramentas/luneta.json +15 -0
- data/src/json/equipamentos/itens/ferramentas/maleta_de_medicamentos.json +17 -0
- data/src/json/equipamentos/itens/ferramentas/sela.json +19 -0
- data/src/json/equipamentos/itens/ferramentas/tambor_das_profundezas.json +17 -0
- data/src/json/equipamentos/itens/servicos/conducao.json +19 -0
- data/src/json/equipamentos/itens/servicos/curandeiro.json +9 -0
- data/src/json/equipamentos/itens/servicos/estadia.json +42 -0
- data/src/json/equipamentos/itens/servicos/magia.json +23 -0
- data/src/json/equipamentos/itens/servicos/mensageiro.json +10 -0
- data/src/json/equipamentos/itens/veiculos/balao_goblin.json +34 -0
- data/src/json/equipamentos/itens/veiculos/canoa.json +18 -0
- data/src/json/equipamentos/itens/veiculos/carroca.json +20 -0
- data/src/json/equipamentos/itens/veiculos/carruagem.json +21 -0
- data/src/json/equipamentos/itens/veiculos/veleiro.json +11 -0
- data/src/json/equipamentos/itens/vestuario/andrajos_de_aldeao.json +16 -0
- data/src/json/equipamentos/itens/vestuario/bandana.json +14 -0
- data/src/json/equipamentos/itens/vestuario/botas_reforcadas.json +15 -0
- data/src/json/equipamentos/itens/vestuario/camisa_bufante.json +14 -0
- data/src/json/equipamentos/itens/vestuario/capa_esvoacante.json +14 -0
- data/src/json/equipamentos/itens/vestuario/capa_pesada.json +14 -0
- data/src/json/equipamentos/itens/vestuario/casaco_longo.json +15 -0
- data/src/json/equipamentos/itens/vestuario/chapeu_arcano.json +15 -0
- data/src/json/equipamentos/itens/vestuario/enfeite_de_elmo.json +15 -0
- data/src/json/equipamentos/itens/vestuario/farrapos_de_ermitao.json +16 -0
- data/src/json/equipamentos/itens/vestuario/gorro_de_ervas.json +14 -0
- data/src/json/equipamentos/itens/vestuario/luva_de_pelica.json +14 -0
- data/src/json/equipamentos/itens/vestuario/manopla.json +15 -0
- data/src/json/equipamentos/itens/vestuario/manto_camuflado.json +20 -0
- data/src/json/equipamentos/itens/vestuario/manto_eclesiastico.json +14 -0
- data/src/json/equipamentos/itens/vestuario/robe_mistico.json +14 -0
- data/src/json/equipamentos/itens/vestuario/sapatos_de_camurca.json +14 -0
- data/src/json/equipamentos/itens/vestuario/tabardo.json +14 -0
- data/src/json/equipamentos/itens/vestuario/traje_da_corte.json +19 -0
- data/src/json/equipamentos/itens/vestuario/traje_de_viajante.json +13 -0
- data/src/json/equipamentos/itens/vestuario/veste_de_seda.json +14 -0
- data/src/json/equipamentos/municoes/balas.json +13 -0
- data/src/json/equipamentos/municoes/flechas.json +13 -0
- data/src/json/equipamentos/municoes/pedras.json +14 -0
- data/src/json/equipamentos/municoes/virotes.json +14 -0
- data/src/json/itens_superiores/materiais_especiais/aco_rubi.json +44 -0
- data/src/json/itens_superiores/materiais_especiais/adamante.json +35 -0
- data/src/json/itens_superiores/materiais_especiais/gelo_eterno.json +33 -0
- data/src/json/itens_superiores/materiais_especiais/madeira_tollon.json +31 -0
- data/src/json/itens_superiores/materiais_especiais/materia_vermelha.json +51 -0
- data/src/json/itens_superiores/materiais_especiais/mitral.json +38 -0
- data/src/json/itens_superiores/melhorias/armaduras_escudos/ajustada.json +11 -0
- data/src/json/itens_superiores/melhorias/armaduras_escudos/delicada.json +15 -0
- data/src/json/itens_superiores/melhorias/armaduras_escudos/espinhosa.json +15 -0
- data/src/json/itens_superiores/melhorias/armaduras_escudos/espinhoso.json +11 -0
- data/src/json/itens_superiores/melhorias/armaduras_escudos/polida.json +13 -0
- data/src/json/itens_superiores/melhorias/armaduras_escudos/reforcada.json +13 -0
- data/src/json/itens_superiores/melhorias/armaduras_escudos/selada.json +14 -0
- data/src/json/itens_superiores/melhorias/armaduras_escudos/sob_medida.json +13 -0
- data/src/json/itens_superiores/melhorias/armas/atroz.json +11 -0
- data/src/json/itens_superiores/melhorias/armas/certeira.json +11 -0
- data/src/json/itens_superiores/melhorias/armas/cruel.json +11 -0
- data/src/json/itens_superiores/melhorias/armas/equilibrada.json +11 -0
- data/src/json/itens_superiores/melhorias/armas/harmonizada.json +13 -0
- data/src/json/itens_superiores/melhorias/armas/injecao_alquimica.json +14 -0
- data/src/json/itens_superiores/melhorias/armas/macica.json +12 -0
- data/src/json/itens_superiores/melhorias/armas/mira_telescopica.json +16 -0
- data/src/json/itens_superiores/melhorias/armas/precisa.json +12 -0
- data/src/json/itens_superiores/melhorias/armas/pungente.json +11 -0
- data/src/json/itens_superiores/melhorias/esotericos/canalizador.json +11 -0
- data/src/json/itens_superiores/melhorias/esotericos/energetico.json +12 -0
- data/src/json/itens_superiores/melhorias/esotericos/harmonizado.json +16 -0
- data/src/json/itens_superiores/melhorias/esotericos/poderoso.json +11 -0
- data/src/json/itens_superiores/melhorias/esotericos/vigilante.json +11 -0
- data/src/json/itens_superiores/melhorias/ferramentas_vestuario/aprimorado.json +15 -0
- data/src/json/itens_superiores/melhorias/geral/banhado_a_ouro.json +17 -0
- data/src/json/itens_superiores/melhorias/geral/cravejado_de_gemas.json +12 -0
- data/src/json/itens_superiores/melhorias/geral/discreto.json +13 -0
- data/src/json/itens_superiores/melhorias/geral/macabro.json +12 -0
- data/src/json/itens_superiores/melhorias/geral/material_especial.json +13 -0
- data/src/json/origens/acolito.json +11 -0
- data/src/json/origens/amigo_dos_animais.json +11 -0
- data/src/json/origens/amnesico.json +10 -0
- data/src/json/origens/aristocrata.json +11 -0
- data/src/json/origens/artesao.json +11 -0
- data/src/json/origens/artista.json +11 -0
- data/src/json/origens/assistente_de_laboratorio.json +11 -0
- data/src/json/origens/batedor.json +11 -0
- data/src/json/origens/capanga.json +11 -0
- data/src/json/origens/charlatao.json +11 -0
- data/src/json/origens/circense.json +11 -0
- data/src/json/origens/criminoso.json +11 -0
- data/src/json/origens/curandeiro.json +11 -0
- data/src/json/origens/eremita.json +11 -0
- data/src/json/origens/escravo.json +11 -0
- data/src/json/origens/estudioso.json +11 -0
- data/src/json/origens/fazendeiro.json +11 -0
- data/src/json/origens/forasteiro.json +11 -0
- data/src/json/origens/gladiador.json +11 -0
- data/src/json/origens/guarda.json +11 -0
- data/src/json/origens/herdeiro.json +11 -0
- data/src/json/origens/heroi_campones.json +11 -0
- data/src/json/origens/marujo.json +11 -0
- data/src/json/origens/mateiro.json +11 -0
- data/src/json/origens/membro_de_guilda.json +11 -0
- data/src/json/origens/mercador.json +11 -0
- data/src/json/origens/minerador.json +11 -0
- data/src/json/origens/nomade.json +11 -0
- data/src/json/origens/pivete.json +11 -0
- data/src/json/origens/refugiado.json +11 -0
- data/src/json/origens/seguidor.json +11 -0
- data/src/json/origens/selvagem.json +11 -0
- data/src/json/origens/soldado.json +11 -0
- data/src/json/origens/taverneiro.json +11 -0
- data/src/json/origens/trabalhador.json +11 -0
- data/src/json/poderes/habilidades_unicas_de_origem/a_prova_de_tudo.json +14 -0
- data/src/json/poderes/habilidades_unicas_de_origem/agua_no_feijao.json +14 -0
- data/src/json/poderes/habilidades_unicas_de_origem/alpinista_social.json +9 -0
- data/src/json/poderes/habilidades_unicas_de_origem/amigo_especial.json +16 -0
- data/src/json/poderes/habilidades_unicas_de_origem/antigo_mestre.json +15 -0
- data/src/json/poderes/habilidades_unicas_de_origem/busca_interior.json +13 -0
- data/src/json/poderes/habilidades_unicas_de_origem/confissao.json +14 -0
- data/src/json/poderes/habilidades_unicas_de_origem/coracao_heroico.json +13 -0
- data/src/json/poderes/habilidades_unicas_de_origem/cultura_exotica.json +13 -0
- data/src/json/poderes/habilidades_unicas_de_origem/desejo_de_liberdade.json +12 -0
- data/src/json/poderes/habilidades_unicas_de_origem/detetive.json +14 -0
- data/src/json/poderes/habilidades_unicas_de_origem/dom_artistico.json +10 -0
- data/src/json/poderes/habilidades_unicas_de_origem/escavador.json +13 -0
- data/src/json/poderes/habilidades_unicas_de_origem/esforcado.json +13 -0
- data/src/json/poderes/habilidades_unicas_de_origem/esse_cheiro.json +14 -0
- data/src/json/poderes/habilidades_unicas_de_origem/estoico.json +16 -0
- data/src/json/poderes/habilidades_unicas_de_origem/frutos_do_trabalho.json +19 -0
- data/src/json/poderes/habilidades_unicas_de_origem/gororoba.json +12 -0
- data/src/json/poderes/habilidades_unicas_de_origem/heranca.json +13 -0
- data/src/json/poderes/habilidades_unicas_de_origem/influencia_militar.json +14 -0
- data/src/json/poderes/habilidades_unicas_de_origem/lembrancas_graduais.json +14 -0
- data/src/json/poderes/habilidades_unicas_de_origem/medico_de_campo.json +12 -0
- data/src/json/poderes/habilidades_unicas_de_origem/membro_da_igreja.json +14 -0
- data/src/json/poderes/habilidades_unicas_de_origem/mochileiro.json +9 -0
- data/src/json/poderes/habilidades_unicas_de_origem/negociacao.json +12 -0
- data/src/json/poderes/habilidades_unicas_de_origem/palpite_fundamentado.json +13 -0
- data/src/json/poderes/habilidades_unicas_de_origem/pao_e_circo.json +11 -0
- data/src/json/poderes/habilidades_unicas_de_origem/passagem_de_navio.json +13 -0
- data/src/json/poderes/habilidades_unicas_de_origem/punguista.json +15 -0
- data/src/json/poderes/habilidades_unicas_de_origem/quebra_galho.json +14 -0
- data/src/json/poderes/habilidades_unicas_de_origem/rede_de_contatos.json +14 -0
- data/src/json/poderes/habilidades_unicas_de_origem/sangue_azul.json +12 -0
- data/src/json/poderes/habilidades_unicas_de_origem/truque_de_magica.json +14 -0
- data/src/json/poderes/habilidades_unicas_de_origem/vendedor_de_carcacas.json +13 -0
- data/src/json/poderes/habilidades_unicas_de_origem/vida_rustica.json +13 -0
- data/src/json/poderes/poderes_concedidos/afinidade_com_a_tormenta.json +14 -0
- data/src/json/poderes/poderes_concedidos/almejar_o_impossivel.json +13 -0
- data/src/json/poderes/poderes_concedidos/anfibio.json +13 -0
- data/src/json/poderes/poderes_concedidos/apostar_com_o_trapaceiro.json +12 -0
- data/src/json/poderes/poderes_concedidos/armas_da_ambicao.json +12 -0
- data/src/json/poderes/poderes_concedidos/arsenal_das_profundezas.json +14 -0
- data/src/json/poderes/poderes_concedidos/astucia_da_serpente.json +14 -0
- data/src/json/poderes/poderes_concedidos/ataque_piedoso.json +13 -0
- data/src/json/poderes/poderes_concedidos/aura_de_medo.json +17 -0
- data/src/json/poderes/poderes_concedidos/aura_de_paz.json +18 -0
- data/src/json/poderes/poderes_concedidos/aura_restauradora.json +13 -0
- data/src/json/poderes/poderes_concedidos/bencao_do_mana.json +10 -0
- data/src/json/poderes/poderes_concedidos/caricia_sombria.json +26 -0
- data/src/json/poderes/poderes_concedidos/centelha_magica.json +13 -0
- data/src/json/poderes/poderes_concedidos/compreender_os_ermos.json +17 -0
- data/src/json/poderes/poderes_concedidos/conhecimento_enciclopedico.json +13 -0
- data/src/json/poderes/poderes_concedidos/conjurar_arma.json +19 -0
- data/src/json/poderes/poderes_concedidos/coragem_total.json +11 -0
- data/src/json/poderes/poderes_concedidos/cura_gentil.json +10 -0
- data/src/json/poderes/poderes_concedidos/curandeira_perfeita.json +15 -0
- data/src/json/poderes/poderes_concedidos/dedo_verde.json +14 -0
- data/src/json/poderes/poderes_concedidos/descanso_natural.json +10 -0
- data/src/json/poderes/poderes_concedidos/dom_da_esperanca.json +15 -0
- data/src/json/poderes/poderes_concedidos/dom_da_imortalidade.json +8 -0
- data/src/json/poderes/poderes_concedidos/dom_da_profecia.json +6 -0
- data/src/json/poderes/poderes_concedidos/dom_da_ressurreicao.json +8 -0
- data/src/json/poderes/poderes_concedidos/dom_da_verdade.json +15 -0
- data/src/json/poderes/poderes_concedidos/escamas_draconicas.json +13 -0
- data/src/json/poderes/poderes_concedidos/escudo_magico.json +12 -0
- data/src/json/poderes/poderes_concedidos/espada_justiceira.json +13 -0
- data/src/json/poderes/poderes_concedidos/espada_solar.json +16 -0
- data/src/json/poderes/poderes_concedidos/extase_da_loucura.json +12 -0
- data/src/json/poderes/poderes_concedidos/familiar_ofidico.json +13 -0
- data/src/json/poderes/poderes_concedidos/farsa_do_fingidor.json +14 -0
- data/src/json/poderes/poderes_concedidos/fe_guerreira.json +20 -0
- data/src/json/poderes/poderes_concedidos/forma_de_macaco.json +20 -0
- data/src/json/poderes/poderes_concedidos/fulgor_solar.json +18 -0
- data/src/json/poderes/poderes_concedidos/furia_divina.json +20 -0
- data/src/json/poderes/poderes_concedidos/golpista_divino.json +14 -0
- data/src/json/poderes/poderes_concedidos/habitante_do_deserto.json +14 -0
- data/src/json/poderes/poderes_concedidos/inimigo_de_tenebra.json +14 -0
- data/src/json/poderes/poderes_concedidos/kiai_divino.json +13 -0
- data/src/json/poderes/poderes_concedidos/liberdade_divina.json +12 -0
- data/src/json/poderes/poderes_concedidos/manto_da_penumbra.json +14 -0
- data/src/json/poderes/poderes_concedidos/mente_analitica.json +16 -0
- data/src/json/poderes/poderes_concedidos/mente_vazia.json +16 -0
- data/src/json/poderes/poderes_concedidos/mestre_dos_mares.json +18 -0
- data/src/json/poderes/poderes_concedidos/olhar_amedrontador.json +14 -0
- data/src/json/poderes/poderes_concedidos/palavras_de_bondade.json +14 -0
- data/src/json/poderes/poderes_concedidos/percepcao_temporal.json +17 -0
- data/src/json/poderes/poderes_concedidos/pesquisa_abencoada.json +15 -0
- data/src/json/poderes/poderes_concedidos/poder_oculto.json +21 -0
- data/src/json/poderes/poderes_concedidos/presas_primordiais.json +23 -0
- data/src/json/poderes/poderes_concedidos/presas_venenosas.json +16 -0
- data/src/json/poderes/poderes_concedidos/rejeicao_divina.json +13 -0
- data/src/json/poderes/poderes_concedidos/reparar_injustica.json +13 -0
- data/src/json/poderes/poderes_concedidos/sangue_de_ferro.json +13 -0
- data/src/json/poderes/poderes_concedidos/sangue_ofidico.json +14 -0
- data/src/json/poderes/poderes_concedidos/servos_do_dragao.json +24 -0
- data/src/json/poderes/poderes_concedidos/sopro_do_mar.json +25 -0
- data/src/json/poderes/poderes_concedidos/sorte_dos_loucos.json +13 -0
- data/src/json/poderes/poderes_concedidos/talento_artistico.json +14 -0
- data/src/json/poderes/poderes_concedidos/teurgista_mistico.json +11 -0
- data/src/json/poderes/poderes_concedidos/tradicao_de_lin_wu.json +14 -0
- data/src/json/poderes/poderes_concedidos/transmissao_da_loucura.json +17 -0
- data/src/json/poderes/poderes_concedidos/tropas_duyshidakk.json +24 -0
- data/src/json/poderes/poderes_concedidos/urro_divino.json +13 -0
- data/src/json/poderes/poderes_concedidos/visao_nas_trevas.json +10 -0
- data/src/json/poderes/poderes_concedidos/voz_da_civilizacao.json +10 -0
- data/src/json/poderes/poderes_concedidos/voz_da_natureza.json +18 -0
- data/src/json/poderes/poderes_concedidos/voz_dos_monstros.json +11 -0
- data/src/json/poderes/poderes_concedidos/zumbificar.json +18 -0
- data/src/json/poderes/poderes_da_tormenta/anatomia_insana.json +12 -0
- data/src/json/poderes/poderes_da_tormenta/antenas.json +18 -0
- data/src/json/poderes/poderes_da_tormenta/armamento_aberrante.json +14 -0
- data/src/json/poderes/poderes_da_tormenta/articulacoes_flexiveis.json +15 -0
- data/src/json/poderes/poderes_da_tormenta/asas_insetoides.json +17 -0
- data/src/json/poderes/poderes_da_tormenta/carapaca.json +12 -0
- data/src/json/poderes/poderes_da_tormenta/corpo_aberrante.json +13 -0
- data/src/json/poderes/poderes_da_tormenta/cuspir_enxame.json +20 -0
- data/src/json/poderes/poderes_da_tormenta/dentes_afiados.json +19 -0
- data/src/json/poderes/poderes_da_tormenta/desprezar_a_realidade.json +21 -0
- data/src/json/poderes/poderes_da_tormenta/empunhadura_rubra.json +13 -0
- data/src/json/poderes/poderes_da_tormenta/fome_de_mana.json +11 -0
- data/src/json/poderes/poderes_da_tormenta/larva_explosiva.json +17 -0
- data/src/json/poderes/poderes_da_tormenta/legiao_aberrante.json +19 -0
- data/src/json/poderes/poderes_da_tormenta/maos_membranosas.json +18 -0
- data/src/json/poderes/poderes_da_tormenta/membros_estendidos.json +12 -0
- data/src/json/poderes/poderes_da_tormenta/membros_extras.json +27 -0
- data/src/json/poderes/poderes_da_tormenta/mente_aberrante.json +20 -0
- data/src/json/poderes/poderes_da_tormenta/olhos_vermelhos.json +12 -0
- data/src/json/poderes/poderes_da_tormenta/pele_corrompida.json +13 -0
- data/src/json/poderes/poderes_da_tormenta/sangue_acido.json +13 -0
- data/src/json/poderes/poderes_da_tormenta/visco_rubro.json +15 -0
- data/src/json/regras/alcances.json +33 -0
- data/src/json/regras/carga.json +47 -0
- data/src/json/regras/critico.json +32 -0
- data/src/json/regras/dinheiro_inicial.json +27 -0
- data/src/json/regras/empunhaduras.json +22 -0
- data/src/json/regras/habilidades_armas.json +37 -0
- data/src/json/regras/itens_superiores.json +19 -0
- data/src/json/regras/limites_uso.json +22 -0
- data/src/json/regras/moedas.json +32 -0
- data/src/json/regras/passos_dano.json +20 -0
- data/src/json/regras/proficiencias.json +32 -0
- data/src/json/regras/propositos_armas.json +37 -0
- data/src/json/regras/tipos_dano.json +25 -0
- data/src/json/regras/venenos.json +45 -0
- data/src/ruby/tormenta20/database.rb +224 -0
- data/src/ruby/tormenta20/models/arma.rb +123 -0
- data/src/ruby/tormenta20/models/armadura.rb +96 -0
- data/src/ruby/tormenta20/models/base.rb +19 -0
- data/src/ruby/tormenta20/models/classe.rb +134 -0
- data/src/ruby/tormenta20/models/divindade.rb +98 -0
- data/src/ruby/tormenta20/models/escudo.rb +59 -0
- data/src/ruby/tormenta20/models/item.rb +61 -0
- data/src/ruby/tormenta20/models/magia.rb +226 -0
- data/src/ruby/tormenta20/models/material_especial.rb +52 -0
- data/src/ruby/tormenta20/models/melhoria.rb +52 -0
- data/src/ruby/tormenta20/models/origem.rb +71 -0
- data/src/ruby/tormenta20/models/poder.rb +120 -0
- data/src/ruby/tormenta20/models/regra.rb +47 -0
- data/src/ruby/tormenta20/seeder.rb +267 -0
- data/src/ruby/tormenta20/version.rb +1 -1
- data/src/ruby/tormenta20.rb +169 -7
- data/src/schema/magia.schema.json +277 -0
- data/src/schema/tormenta20.sql +433 -0
- data/tasks/jsonlint.rb +6 -4
- data/tools/pdf_extractor/README.md +171 -0
- data/tools/pdf_extractor/__init__.py +17 -0
- data/tools/pdf_extractor/pdf_extractor.py +441 -0
- data/tools/pdf_extractor/pipeline.py +450 -0
- data/tools/pdf_extractor/prompts.py +789 -0
- data/tools/pdf_extractor/requirements.txt +4 -0
- metadata +488 -12
- data/src/ruby/open_struct_json.rb +0 -35
- data/src/ruby/tormenta20/classes.rb +0 -0
- data/src/ruby/tormenta20/equipment.rb +0 -0
- data/src/ruby/tormenta20/magias.rb +0 -35
- data/src/ruby/tormenta20/origins.rb +0 -0
- data/src/ruby/tormenta20/races.rb +0 -0
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Extrator de texto do PDF do Tormenta 20.
|
|
3
|
+
Processa o índice e divide o conteúdo em seções para processamento.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import pdfplumber
|
|
7
|
+
import re
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Generator
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class TableOfContentsEntry:
|
|
15
|
+
"""Entrada do índice."""
|
|
16
|
+
title: str
|
|
17
|
+
page: int
|
|
18
|
+
level: int # 0 = capítulo, 1 = seção, 2 = subseção
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class PDFExtractor:
|
|
22
|
+
def __init__(self, pdf_path: str):
|
|
23
|
+
self.pdf_path = Path(pdf_path)
|
|
24
|
+
self.text = ""
|
|
25
|
+
self.pages: list[dict] = []
|
|
26
|
+
self.toc: list[TableOfContentsEntry] = []
|
|
27
|
+
self.sections: dict = {}
|
|
28
|
+
|
|
29
|
+
def extract(self) -> str:
|
|
30
|
+
"""Extrai todo o texto do PDF."""
|
|
31
|
+
with pdfplumber.open(self.pdf_path) as pdf:
|
|
32
|
+
for i, page in enumerate(pdf.pages):
|
|
33
|
+
page_text = page.extract_text() or ""
|
|
34
|
+
self.pages.append({
|
|
35
|
+
"number": i + 1,
|
|
36
|
+
"text": page_text
|
|
37
|
+
})
|
|
38
|
+
self.text += f"\n--- PÁGINA {i + 1} ---\n{page_text}"
|
|
39
|
+
|
|
40
|
+
return self.text
|
|
41
|
+
|
|
42
|
+
def extract_table_of_contents(self, toc_start_page: int = 3, toc_end_page: int = 6) -> list[TableOfContentsEntry]:
|
|
43
|
+
"""
|
|
44
|
+
Extrai o índice do PDF.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
toc_start_page: Página inicial do índice
|
|
48
|
+
toc_end_page: Página final do índice
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Lista de entradas do índice
|
|
52
|
+
"""
|
|
53
|
+
if not self.pages:
|
|
54
|
+
self.extract()
|
|
55
|
+
|
|
56
|
+
toc_text = self.get_pages_range(toc_start_page, toc_end_page)
|
|
57
|
+
|
|
58
|
+
# Padrão para linhas do índice: "Título ... número" ou "Título número"
|
|
59
|
+
# Captura títulos com páginas
|
|
60
|
+
pattern = r'^(.+?)\s*\.{2,}\s*(\d+)\s*$|^(.+?)\s+(\d+)\s*$'
|
|
61
|
+
|
|
62
|
+
entries = []
|
|
63
|
+
for line in toc_text.split('\n'):
|
|
64
|
+
line = line.strip()
|
|
65
|
+
if not line:
|
|
66
|
+
continue
|
|
67
|
+
|
|
68
|
+
match = re.match(pattern, line)
|
|
69
|
+
if match:
|
|
70
|
+
if match.group(1): # Padrão com pontos
|
|
71
|
+
title = match.group(1).strip()
|
|
72
|
+
page = int(match.group(2))
|
|
73
|
+
else: # Padrão sem pontos
|
|
74
|
+
title = match.group(3).strip()
|
|
75
|
+
page = int(match.group(4))
|
|
76
|
+
|
|
77
|
+
# Determinar nível baseado em indentação ou formatação
|
|
78
|
+
level = 0
|
|
79
|
+
if line.startswith(' ') or line.startswith('\t'):
|
|
80
|
+
level = 1
|
|
81
|
+
if line.startswith(' ') or line.startswith('\t\t'):
|
|
82
|
+
level = 2
|
|
83
|
+
|
|
84
|
+
entries.append(TableOfContentsEntry(title=title, page=page, level=level))
|
|
85
|
+
|
|
86
|
+
self.toc = entries
|
|
87
|
+
return entries
|
|
88
|
+
|
|
89
|
+
def build_sections_from_toc(self) -> dict:
|
|
90
|
+
"""
|
|
91
|
+
Constrói o mapeamento de seções a partir do índice.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Dicionário com seções e suas páginas
|
|
95
|
+
"""
|
|
96
|
+
if not self.toc:
|
|
97
|
+
self.extract_table_of_contents()
|
|
98
|
+
|
|
99
|
+
sections = {}
|
|
100
|
+
for i, entry in enumerate(self.toc):
|
|
101
|
+
# Criar slug a partir do título
|
|
102
|
+
slug = self._slugify(entry.title)
|
|
103
|
+
|
|
104
|
+
# Determinar página final (próxima entrada ou fim do documento)
|
|
105
|
+
if i + 1 < len(self.toc):
|
|
106
|
+
end_page = self.toc[i + 1].page - 1
|
|
107
|
+
else:
|
|
108
|
+
end_page = len(self.pages)
|
|
109
|
+
|
|
110
|
+
sections[slug] = {
|
|
111
|
+
"title": entry.title,
|
|
112
|
+
"start_page": entry.page,
|
|
113
|
+
"end_page": end_page,
|
|
114
|
+
"level": entry.level
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
self.sections = sections
|
|
118
|
+
return sections
|
|
119
|
+
|
|
120
|
+
def _slugify(self, text: str) -> str:
|
|
121
|
+
"""Converte texto para slug."""
|
|
122
|
+
# Remove acentos
|
|
123
|
+
replacements = {
|
|
124
|
+
'á': 'a', 'à': 'a', 'ã': 'a', 'â': 'a', 'ä': 'a',
|
|
125
|
+
'é': 'e', 'è': 'e', 'ê': 'e', 'ë': 'e',
|
|
126
|
+
'í': 'i', 'ì': 'i', 'î': 'i', 'ï': 'i',
|
|
127
|
+
'ó': 'o', 'ò': 'o', 'õ': 'o', 'ô': 'o', 'ö': 'o',
|
|
128
|
+
'ú': 'u', 'ù': 'u', 'û': 'u', 'ü': 'u',
|
|
129
|
+
'ç': 'c', 'ñ': 'n'
|
|
130
|
+
}
|
|
131
|
+
text = text.lower()
|
|
132
|
+
for char, replacement in replacements.items():
|
|
133
|
+
text = text.replace(char, replacement)
|
|
134
|
+
|
|
135
|
+
# Remove caracteres especiais e substitui espaços
|
|
136
|
+
text = re.sub(r'[^a-z0-9\s]', '', text)
|
|
137
|
+
text = re.sub(r'\s+', '_', text.strip())
|
|
138
|
+
return text
|
|
139
|
+
|
|
140
|
+
def get_pages_range(self, start: int, end: int) -> str:
|
|
141
|
+
"""Retorna o texto de um intervalo de páginas."""
|
|
142
|
+
return "\n".join(
|
|
143
|
+
p["text"] for p in self.pages
|
|
144
|
+
if start <= p["number"] <= end
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
def get_section_text(self, section_slug: str) -> str:
|
|
148
|
+
"""Retorna o texto de uma seção específica."""
|
|
149
|
+
if not self.sections:
|
|
150
|
+
self.build_sections_from_toc()
|
|
151
|
+
|
|
152
|
+
if section_slug not in self.sections:
|
|
153
|
+
# Tenta busca parcial
|
|
154
|
+
matches = [k for k in self.sections.keys() if section_slug in k]
|
|
155
|
+
if matches:
|
|
156
|
+
section_slug = matches[0]
|
|
157
|
+
else:
|
|
158
|
+
raise ValueError(f"Seção não encontrada: {section_slug}")
|
|
159
|
+
|
|
160
|
+
section = self.sections[section_slug]
|
|
161
|
+
return self.get_pages_range(section["start_page"], section["end_page"])
|
|
162
|
+
|
|
163
|
+
def list_sections(self) -> list[str]:
|
|
164
|
+
"""Lista todas as seções disponíveis."""
|
|
165
|
+
if not self.sections:
|
|
166
|
+
self.build_sections_from_toc()
|
|
167
|
+
return list(self.sections.keys())
|
|
168
|
+
|
|
169
|
+
def find_section(self, start_pattern: str, end_pattern: str = None) -> str:
|
|
170
|
+
"""Encontra uma seção do texto baseado em padrões."""
|
|
171
|
+
start_match = re.search(start_pattern, self.text, re.IGNORECASE)
|
|
172
|
+
if not start_match:
|
|
173
|
+
return ""
|
|
174
|
+
|
|
175
|
+
start_idx = start_match.start()
|
|
176
|
+
|
|
177
|
+
if end_pattern:
|
|
178
|
+
end_match = re.search(end_pattern, self.text[start_idx + 1:], re.IGNORECASE)
|
|
179
|
+
end_idx = start_idx + 1 + end_match.start() if end_match else len(self.text)
|
|
180
|
+
else:
|
|
181
|
+
end_idx = len(self.text)
|
|
182
|
+
|
|
183
|
+
return self.text[start_idx:end_idx]
|
|
184
|
+
|
|
185
|
+
def split_by_headers(self, text: str, header_pattern: str) -> Generator[dict, None, None]:
|
|
186
|
+
"""Divide o texto por cabeçalhos."""
|
|
187
|
+
matches = list(re.finditer(header_pattern, text, re.MULTILINE))
|
|
188
|
+
|
|
189
|
+
for i, match in enumerate(matches):
|
|
190
|
+
start = match.start()
|
|
191
|
+
end = matches[i + 1].start() if i + 1 < len(matches) else len(text)
|
|
192
|
+
|
|
193
|
+
yield {
|
|
194
|
+
"header": match.group().strip(),
|
|
195
|
+
"content": text[start:end].strip()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
# Padrões de cabeçalho por tipo de entidade
|
|
200
|
+
# Organizados por capítulo do livro
|
|
201
|
+
ENTITY_PATTERNS = {
|
|
202
|
+
# ===========================================
|
|
203
|
+
# CAPÍTULO 1: CONSTRUÇÃO DE PERSONAGEM
|
|
204
|
+
# ===========================================
|
|
205
|
+
|
|
206
|
+
# Raças (págs. 18-31)
|
|
207
|
+
"racas": r"^([A-Z][a-zá-ú]+(?:/[a-zá-ú]+)?(?:\s+[A-Z][a-zá-ú]+)*)\n(?:Destreza|Força|Inteligência|Carisma|Constituição|Sabedoria|\+1)",
|
|
208
|
+
|
|
209
|
+
# Classes (págs. 32-84)
|
|
210
|
+
"classes": r"^(Arcanista|Bárbaro|Bardo|Bucaneiro|Caçador|Cavaleiro|Clérigo|Druida|Guerreiro|Inventor|Ladino|Lutador|Nobre|Paladino)\n",
|
|
211
|
+
|
|
212
|
+
# Origens (págs. 85-95)
|
|
213
|
+
"origens": r"^([A-Z][a-zá-ú]+(?:\s+(?:de\s+)?[a-zA-Zá-ú]+)*)\n(?:Você|Itens\.|Neste|Este|Esta)",
|
|
214
|
+
|
|
215
|
+
# Deuses/Divindades (págs. 96-105)
|
|
216
|
+
"divindades": r"^([A-Z][a-zá-ú]+(?:-[A-Z][a-zá-ú]+)?)\n(?:Crenças|Outrora|A Deusa|O Deus|Este|Esta|Também|Diz-se|Ainda)",
|
|
217
|
+
|
|
218
|
+
# ===========================================
|
|
219
|
+
# CAPÍTULO 2: PERÍCIAS & PODERES
|
|
220
|
+
# ===========================================
|
|
221
|
+
|
|
222
|
+
# Perícias (págs. 114-123)
|
|
223
|
+
"pericias": r"^([A-Z][a-zá-ú]+)\s+(For|Des|Int|Sab|Car|Con)(?:\s+[•·])?",
|
|
224
|
+
|
|
225
|
+
# Poderes Gerais (págs. 124-137)
|
|
226
|
+
"poderes": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\n(?:Você|Quando|Sua|Seu|Pré-requisito|Uma vez|No início|Durante)",
|
|
227
|
+
|
|
228
|
+
# Poderes de Combate (págs. 124-128)
|
|
229
|
+
"poderes_combate": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\n(?:Você|Quando|Sua|Seu|Pré-requisito|Uma vez)",
|
|
230
|
+
|
|
231
|
+
# Poderes de Destino (págs. 129-130)
|
|
232
|
+
"poderes_destino": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\n(?:Você|Quando|Sua|Seu|Pré-requisito)",
|
|
233
|
+
|
|
234
|
+
# Poderes de Magia (págs. 131)
|
|
235
|
+
"poderes_magia": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\n(?:Você|Quando|Sua|Seu|Pré-requisito)",
|
|
236
|
+
|
|
237
|
+
# Poderes Concedidos (págs. 132-135)
|
|
238
|
+
"poderes_concedidos": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\n(?:Você|Quando|Sua|Seu|Pré-requisito|Uma vez|No início)",
|
|
239
|
+
|
|
240
|
+
# Poderes da Tormenta (págs. 136-137)
|
|
241
|
+
"poderes_tormenta": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\n(?:Você|Quando|Sua|Seu|Pré-requisito|Uma vez)",
|
|
242
|
+
|
|
243
|
+
# ===========================================
|
|
244
|
+
# CAPÍTULO 3: EQUIPAMENTO
|
|
245
|
+
# ===========================================
|
|
246
|
+
|
|
247
|
+
# Armas (págs. 142-151) - geralmente em tabelas
|
|
248
|
+
"armas": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\s+T\$\s*\d+",
|
|
249
|
+
|
|
250
|
+
# Armaduras & Escudos (págs. 152-154)
|
|
251
|
+
"armaduras": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\s+T\$\s*\d+",
|
|
252
|
+
|
|
253
|
+
# Itens Gerais (págs. 155-163)
|
|
254
|
+
"itens_gerais": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\s*[\.:]?\s*(?:T\$|Este|Esta|Um|Uma|Você)",
|
|
255
|
+
|
|
256
|
+
# Itens Superiores (págs. 164-167)
|
|
257
|
+
"itens_superiores": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\s*[\.:]?\s*(?:T\$|Este|Esta|Um|Uma|Arma|Armadura)",
|
|
258
|
+
|
|
259
|
+
# ===========================================
|
|
260
|
+
# CAPÍTULO 4: MAGIA
|
|
261
|
+
# ===========================================
|
|
262
|
+
|
|
263
|
+
# Magias (págs. 178-211)
|
|
264
|
+
"magias": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\n(?:Arcana|Divina|Universal)",
|
|
265
|
+
|
|
266
|
+
# ===========================================
|
|
267
|
+
# CAPÍTULO 7: AMEAÇAS
|
|
268
|
+
# ===========================================
|
|
269
|
+
|
|
270
|
+
# Criaturas/Monstros (págs. 282-316)
|
|
271
|
+
"criaturas": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\s+ND\s*\d+",
|
|
272
|
+
|
|
273
|
+
# Perigos (págs. 317-321)
|
|
274
|
+
"perigos": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\n(?:Este|Esta|Um|Uma|Perigo|Armadilha)",
|
|
275
|
+
|
|
276
|
+
# ===========================================
|
|
277
|
+
# CAPÍTULO 8: RECOMPENSAS
|
|
278
|
+
# ===========================================
|
|
279
|
+
|
|
280
|
+
# Tesouros (págs. 327-332)
|
|
281
|
+
"tesouros": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\s*[\.:]?\s*(?:T\$|Este|Esta|Um|Uma)",
|
|
282
|
+
|
|
283
|
+
# Itens Mágicos - Armas (págs. 335-337)
|
|
284
|
+
"itens_magicos_armas": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\s*(?:\([^)]+\))?\s*\n(?:Esta arma|Este|Arma)",
|
|
285
|
+
|
|
286
|
+
# Itens Mágicos - Armaduras (págs. 338-340)
|
|
287
|
+
"itens_magicos_armaduras": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\s*(?:\([^)]+\))?\s*\n(?:Esta armadura|Este escudo|Armadura|Escudo)",
|
|
288
|
+
|
|
289
|
+
# Poções & Pergaminhos (págs. 341)
|
|
290
|
+
"pocoes_pergaminhos": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\s*(?:\([^)]+\))?\s*\n(?:Esta poção|Este pergaminho|Poção|Pergaminho)",
|
|
291
|
+
|
|
292
|
+
# Acessórios (págs. 342-345)
|
|
293
|
+
"acessorios": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\s*(?:\([^)]+\))?\s*\n(?:Este|Esta|Um|Uma|Anel|Amuleto|Botas|Capa|Manto)",
|
|
294
|
+
|
|
295
|
+
# Artefatos (págs. 346-349)
|
|
296
|
+
"artefatos": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\s*(?:\([^)]+\))?\s*\n(?:Este|Esta|Um|Uma|Artefato|Lendário)",
|
|
297
|
+
|
|
298
|
+
# ===========================================
|
|
299
|
+
# OUTROS
|
|
300
|
+
# ===========================================
|
|
301
|
+
|
|
302
|
+
# Condições (pág. 394)
|
|
303
|
+
"condicoes": r"^([A-Z][a-zá-ú]+)\s*[\.:]?\s*(?:você|uma criatura|o personagem|a criatura)",
|
|
304
|
+
|
|
305
|
+
# Padrão genérico - fallback
|
|
306
|
+
"generico": r"^([A-Z][a-zá-ú]+(?:\s+[a-zA-Zá-ú]+)*)\n"
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
# Mapeamento de seções do sumário para tipos de entidade
|
|
310
|
+
SECTION_TO_ENTITY_TYPE = {
|
|
311
|
+
"racas": "racas",
|
|
312
|
+
"raças": "racas",
|
|
313
|
+
"humano": "racas",
|
|
314
|
+
"anao": "racas",
|
|
315
|
+
"classes": "classes",
|
|
316
|
+
"arcanista": "classes",
|
|
317
|
+
"barbaro": "classes",
|
|
318
|
+
"origens": "origens",
|
|
319
|
+
"deuses": "divindades",
|
|
320
|
+
"pericias": "pericias",
|
|
321
|
+
"poderes_gerais": "poderes",
|
|
322
|
+
"poderes_de_combate": "poderes_combate",
|
|
323
|
+
"poderes_de_destino": "poderes_destino",
|
|
324
|
+
"poderes_de_magia": "poderes_magia",
|
|
325
|
+
"poderes_concedidos": "poderes_concedidos",
|
|
326
|
+
"poderes_da_tormenta": "poderes_tormenta",
|
|
327
|
+
"armas": "armas",
|
|
328
|
+
"armaduras_escudos": "armaduras",
|
|
329
|
+
"itens_gerais": "itens_gerais",
|
|
330
|
+
"itens_superiores": "itens_superiores",
|
|
331
|
+
"descricao_das_magias": "magias",
|
|
332
|
+
"criaturas": "criaturas",
|
|
333
|
+
"perigos": "perigos",
|
|
334
|
+
"tesouros": "tesouros",
|
|
335
|
+
"itens_magicos": "itens_magicos_armas", # default
|
|
336
|
+
"pocoes_pergaminhos": "pocoes_pergaminhos",
|
|
337
|
+
"acessorios": "acessorios",
|
|
338
|
+
"artefatos": "artefatos",
|
|
339
|
+
"lista_de_condicoes": "condicoes",
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
def extract_entities(pdf_path: str, section_name: str, entity_type: str = None) -> list[dict]:
|
|
344
|
+
"""
|
|
345
|
+
Extrai entidades de uma seção específica do PDF.
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
pdf_path: Caminho para o PDF
|
|
349
|
+
section_name: Nome/slug da seção (do índice)
|
|
350
|
+
entity_type: Tipo de entidade para usar padrão correto (opcional).
|
|
351
|
+
Se não especificado, tenta inferir pelo nome da seção.
|
|
352
|
+
|
|
353
|
+
Returns:
|
|
354
|
+
Lista de dicionários com header e content de cada entidade
|
|
355
|
+
"""
|
|
356
|
+
extractor = PDFExtractor(pdf_path)
|
|
357
|
+
extractor.extract()
|
|
358
|
+
extractor.build_sections_from_toc()
|
|
359
|
+
|
|
360
|
+
section_text = extractor.get_section_text(section_name)
|
|
361
|
+
|
|
362
|
+
# Tentar inferir tipo de entidade pelo nome da seção
|
|
363
|
+
if not entity_type:
|
|
364
|
+
# Busca no mapeamento
|
|
365
|
+
section_lower = section_name.lower()
|
|
366
|
+
for key, value in SECTION_TO_ENTITY_TYPE.items():
|
|
367
|
+
if key in section_lower or section_lower in key:
|
|
368
|
+
entity_type = value
|
|
369
|
+
break
|
|
370
|
+
|
|
371
|
+
# Usar padrão específico ou genérico
|
|
372
|
+
if entity_type and entity_type in ENTITY_PATTERNS:
|
|
373
|
+
pattern = ENTITY_PATTERNS[entity_type]
|
|
374
|
+
else:
|
|
375
|
+
# Padrão genérico: linha começando com maiúscula seguida de quebra
|
|
376
|
+
pattern = ENTITY_PATTERNS["generico"]
|
|
377
|
+
|
|
378
|
+
entities = list(extractor.split_by_headers(section_text, pattern))
|
|
379
|
+
return entities
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def list_available_sections(pdf_path: str, toc_start: int = 3, toc_end: int = 6) -> dict:
|
|
383
|
+
"""
|
|
384
|
+
Lista todas as seções disponíveis no PDF.
|
|
385
|
+
|
|
386
|
+
Args:
|
|
387
|
+
pdf_path: Caminho para o PDF
|
|
388
|
+
toc_start: Página inicial do índice
|
|
389
|
+
toc_end: Página final do índice
|
|
390
|
+
|
|
391
|
+
Returns:
|
|
392
|
+
Dicionário com seções e suas informações
|
|
393
|
+
"""
|
|
394
|
+
extractor = PDFExtractor(pdf_path)
|
|
395
|
+
extractor.extract()
|
|
396
|
+
extractor.extract_table_of_contents(toc_start, toc_end)
|
|
397
|
+
return extractor.build_sections_from_toc()
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
if __name__ == "__main__":
|
|
401
|
+
import sys
|
|
402
|
+
|
|
403
|
+
if len(sys.argv) < 2:
|
|
404
|
+
print("Uso:")
|
|
405
|
+
print(" python pdf_extractor.py <caminho_pdf> --list-sections")
|
|
406
|
+
print(" python pdf_extractor.py <caminho_pdf> <secao> [tipo_entidade]")
|
|
407
|
+
print(f"\nTipos de entidade disponíveis: {list(ENTITY_PATTERNS.keys())}")
|
|
408
|
+
sys.exit(1)
|
|
409
|
+
|
|
410
|
+
pdf_path = sys.argv[1]
|
|
411
|
+
|
|
412
|
+
if len(sys.argv) >= 3 and sys.argv[2] == "--list-sections":
|
|
413
|
+
# Listar seções
|
|
414
|
+
toc_start = int(sys.argv[3]) if len(sys.argv) > 3 else 3
|
|
415
|
+
toc_end = int(sys.argv[4]) if len(sys.argv) > 4 else 6
|
|
416
|
+
|
|
417
|
+
sections = list_available_sections(pdf_path, toc_start, toc_end)
|
|
418
|
+
print("\nSeções encontradas no índice:")
|
|
419
|
+
print("=" * 60)
|
|
420
|
+
for slug, info in sections.items():
|
|
421
|
+
print(f"{slug}: páginas {info['start_page']}-{info['end_page']} ({info['title']})")
|
|
422
|
+
sys.exit(0)
|
|
423
|
+
|
|
424
|
+
if len(sys.argv) < 3:
|
|
425
|
+
print("Erro: especifique a seção ou use --list-sections")
|
|
426
|
+
sys.exit(1)
|
|
427
|
+
|
|
428
|
+
section = sys.argv[2]
|
|
429
|
+
entity_type = sys.argv[3] if len(sys.argv) > 3 else None
|
|
430
|
+
|
|
431
|
+
entities = extract_entities(pdf_path, section, entity_type)
|
|
432
|
+
|
|
433
|
+
print(f"\nEncontradas {len(entities)} entidades na seção '{section}':")
|
|
434
|
+
print("=" * 60)
|
|
435
|
+
|
|
436
|
+
for entity in entities:
|
|
437
|
+
print(f"\n{'='*50}")
|
|
438
|
+
print(f"ENTIDADE: {entity['header']}")
|
|
439
|
+
print(f"{'='*50}")
|
|
440
|
+
preview = entity['content'][:500]
|
|
441
|
+
print(preview + ("..." if len(entity['content']) > 500 else ""))
|