2024-10-09 22:44:40 +00:00
import functools
import json
from flask import Blueprint , jsonify
import jsonpickle
from sqlalchemy import create_engine , select
from sqlalchemy . orm import Session
2024-10-16 13:52:47 +00:00
from . database import get_database , get_jiten_db
2024-10-09 22:44:40 +00:00
blueprint = Blueprint ( " api " , __name__ , url_prefix = " /api " )
@blueprint.route ( " / " )
def logout ( ) :
# db = get_database()
return {
" endpoints " : [ " id " , " kanji " , " kotoba (not implemented) " ]
}
import random
import sqlalchemy
from typing import List , Optional , Iterable
from sqlalchemy import URL , ForeignKey , String , Boolean , Text , Integer
from sqlalchemy . types import CHAR
from sqlalchemy . orm import DeclarativeBase , Mapped , Session , mapped_column , relationship
class Base ( DeclarativeBase ) :
pass
# class Reading(Base):
# __tablename__ = "reading"
# id: Mapped[int] = mapped_column(primary_key=True)
# reading: Mapped[str] = mapped_column(String(length=10)) # Assume no reading can be over 10 characters long, a sound assumption overall
# kanji_id: Mapped[int] = mapped_column(ForeignKey("kanji.id"))
# kanji: Mapped["Kanji"] = relationship(back_populates="readings")
# reading_type: Mapped[str] = mapped_column(CHAR(1), primary_key=True) # One of: 音漢呉慣唐宋訓
class Goon ( Base ) :
__tablename__ = " goon "
id : Mapped [ int ] = mapped_column ( primary_key = True )
reading : Mapped [ str ] = mapped_column ( String ( length = 10 ) ) # Assume no reading can be over 10 characters long, a sound assumption overall
kanji_id : Mapped [ int ] = mapped_column ( ForeignKey ( " kanji.id " ) )
kanji : Mapped [ " Kanji " ] = relationship ( back_populates = " goon " )
# reading_type: Mapped[str] = mapped_column(CHAR(1), primary_key=True) # One of: 音漢呉慣唐宋訓
class Kanon ( Base ) :
__tablename__ = " kanon "
id : Mapped [ int ] = mapped_column ( primary_key = True )
reading : Mapped [ str ] = mapped_column ( String ( length = 10 ) ) # Assume no reading can be over 10 characters long, a sound assumption overall
kanji_id : Mapped [ int ] = mapped_column ( ForeignKey ( " kanji.id " ) )
kanji : Mapped [ " Kanji " ] = relationship ( back_populates = " kanon " )
# reading_type: Mapped[str] = mapped_column(CHAR(1), primary_key=True) # One of: 音漢呉慣唐宋訓
class Kanyoon ( Base ) :
__tablename__ = " kanyoon "
id : Mapped [ int ] = mapped_column ( primary_key = True )
reading : Mapped [ str ] = mapped_column ( String ( length = 10 ) ) # Assume no reading can be over 10 characters long, a sound assumption overall
kanji_id : Mapped [ int ] = mapped_column ( ForeignKey ( " kanji.id " ) )
kanji : Mapped [ " Kanji " ] = relationship ( back_populates = " kanyoon " )
# reading_type: Mapped[str] = mapped_column(CHAR(1), primary_key=True) # One of: 音漢呉慣唐宋訓
class Soon ( Base ) :
__tablename__ = " soon "
id : Mapped [ int ] = mapped_column ( primary_key = True )
reading : Mapped [ str ] = mapped_column ( String ( length = 10 ) ) # Assume no reading can be over 10 characters long, a sound assumption overall
kanji_id : Mapped [ int ] = mapped_column ( ForeignKey ( " kanji.id " ) )
kanji : Mapped [ " Kanji " ] = relationship ( back_populates = " soon " )
# reading_type: Mapped[str] = mapped_column(CHAR(1), primary_key=True) # One of: 音漢呉慣唐宋訓
class Toon ( Base ) :
__tablename__ = " toon "
id : Mapped [ int ] = mapped_column ( primary_key = True )
reading : Mapped [ str ] = mapped_column ( String ( length = 10 ) ) # Assume no reading can be over 10 characters long, a sound assumption overall
kanji_id : Mapped [ int ] = mapped_column ( ForeignKey ( " kanji.id " ) )
kanji : Mapped [ " Kanji " ] = relationship ( back_populates = " toon " )
# reading_type: Mapped[str] = mapped_column(CHAR(1), primary_key=True) # One of: 音漢呉慣唐宋訓
class Kun ( Base ) :
__tablename__ = " kun "
id : Mapped [ int ] = mapped_column ( primary_key = True )
reading : Mapped [ str ] = mapped_column ( String ( length = 10 ) ) # Assume no reading can be over 10 characters long, a sound assumption overall
kanji_id : Mapped [ int ] = mapped_column ( ForeignKey ( " kanji.id " ) )
kanji : Mapped [ " Kanji " ] = relationship ( back_populates = " kun " )
# reading_type: Mapped[str] = mapped_column(CHAR(1), primary_key=True) # One of: 音漢呉慣唐宋訓
class UnclassifiedOn ( Base ) :
__tablename__ = " unclassified_on "
id : Mapped [ int ] = mapped_column ( primary_key = True )
reading : Mapped [ str ] = mapped_column ( String ( length = 10 ) ) # Assume no reading can be over 10 characters long, a sound assumption overall
kanji_id : Mapped [ int ] = mapped_column ( ForeignKey ( " kanji.id " ) )
kanji : Mapped [ " Kanji " ] = relationship ( back_populates = " unclassified_on " )
# reading_type: Mapped[str] = mapped_column(CHAR(1), primary_key=True) # One of: 音漢呉慣唐宋訓
class Kanji ( Base ) :
__tablename__ = " kanji "
id : Mapped [ int ] = mapped_column ( primary_key = True )
character : Mapped [ str ] = mapped_column ( CHAR ( length = 1 ) , unique = True )
level : Mapped [ str ] = mapped_column ( String ( length = 2 ) ) # Either 1, 2, etc. or 準2 etc.
is_kokuji : Mapped [ bool ] = mapped_column ( Boolean ( ) )
meanings : Mapped [ str ] = mapped_column ( Text ( ) ) # FIXME: make this a list
# readings: Mapped[List[Reading]] = relationship(back_populates="kanji")
goon : Mapped [ List [ Goon ] ] = relationship ( back_populates = " kanji " )
kanon : Mapped [ List [ Kanon ] ] = relationship ( back_populates = " kanji " )
kanyoon : Mapped [ List [ Kanyoon ] ] = relationship ( back_populates = " kanji " )
toon : Mapped [ List [ Toon ] ] = relationship ( back_populates = " kanji " )
soon : Mapped [ List [ Soon ] ] = relationship ( back_populates = " kanji " )
kun : Mapped [ List [ Kun ] ] = relationship ( back_populates = " kanji " )
unclassified_on : Mapped [ List [ UnclassifiedOn ] ] = relationship ( back_populates = " kanji " )
radical : Mapped [ str ] = mapped_column ( CHAR ( length = 1 ) ) # FIXME: normalize?
stroke_count : Mapped [ int ] = mapped_column ( Integer ( ) )
radical_added_stroke_count : Mapped [ int ] = mapped_column ( Integer ( ) ) # FIXME: normalize? this may theoretically be calculated based on the radical stroke count, but I need to validate that this always works
glyph_origin : Mapped [ str ] = mapped_column ( Text ( ) ) # FIXME: make this a list of possible explanations, possibly, but unsure
# diagram: Mapped[str] = ... could be calculated from the kanji name
def to_json ( self ) :
out = { }
for attr , value in self . __dict__ . items ( ) :
if not isinstance ( value , ( bool , int , str ) ) :
continue
else :
out [ attr ] = value
for attr in ( " goon " , " kanon " , " kanyoon " , " toon " , " soon " , " kun " , " unclassified_on " ) :
out [ attr ] = [ reading_obj . reading for reading_obj in getattr ( self , attr ) ]
return out
2024-10-21 10:14:25 +00:00
def render ( self ) :
return self . character
2024-10-09 22:44:40 +00:00
@blueprint.route ( " /id/<int:kanji_id> " )
def kanji_by_id ( kanji_id : int ) :
2024-10-16 13:52:47 +00:00
session = get_jiten_db ( )
query = select ( Kanji ) . where ( Kanji . id == kanji_id )
item = session . execute ( query ) . first ( )
if item is None :
return " Invalid ID " , 404
kanji = item [ 0 ]
return kanji . to_json ( )
def get_kanji_by_character ( kanji : str ) - > Kanji :
session = get_jiten_db ( )
query = select ( Kanji ) . where ( Kanji . character == kanji )
item = session . execute ( query ) . first ( )
if item is None :
return " Invalid kanji " , 404
kanji_obj : Kanji = item [ 0 ]
return kanji_obj
2024-10-09 22:44:40 +00:00
@blueprint.route ( " /kanji/<kanji> " )
def kanji_by_character ( kanji : str ) :
2024-10-16 13:52:47 +00:00
kanji_obj = get_kanji_by_character ( kanji )
return kanji_obj . to_json ( )
def get_kanji_generic ( ) :
pass