Skip to content

Commit

Permalink
Merge pull request #10 from pingpingy1/main
Browse files Browse the repository at this point in the history
[feat] 국회의원 정보 반환
  • Loading branch information
pingpingy1 committed Nov 29, 2023
2 parents 1c9ffb2 + 4ee89bd commit f1857cd
Show file tree
Hide file tree
Showing 10 changed files with 1,282 additions and 146 deletions.
9 changes: 8 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
from fastapi import FastAPI, Request
from dotenv import load_dotenv
from routers import commonInfo, ageHist, scrapResultLocal, scrapResultMetro
from routers import (
commonInfo,
ageHist,
scrapResultLocal,
scrapResultMetro,
scrapResultNational,
)
from contextlib import asynccontextmanager
from typing import Dict
from model import MongoDB
Expand Down Expand Up @@ -35,5 +41,6 @@ async def initMongo(app: FastAPI):

app.include_router(scrapResultLocal.router)
app.include_router(scrapResultMetro.router)
app.include_router(scrapResultNational.router)
app.include_router(commonInfo.router)
app.include_router(ageHist.router)
4 changes: 4 additions & 0 deletions model/AgeHist.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ class AgeHistDataPoint(BaseModel):
ageGroup: int


class NationalAgeHistData(BaseModel):
data: list[AgeHistDataPoint]


class MetroAgeHistData(BaseModel):
metroId: int
data: list[AgeHistDataPoint]
Expand Down
10 changes: 10 additions & 0 deletions model/BasicResponse.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
SUCCESS = 200
REGION_CODE_ERR = 400
COLLECTION_NOT_EXIST_ERR = 600
NO_DATA_ERROR = 800


class MessageResponse(BaseModel):
Expand All @@ -15,3 +16,12 @@ class ErrorResponse(BaseModel):
error: str
code: int
message: str


NO_DATA_ERROR_RESPONSE: ErrorResponse = ErrorResponse.model_validate(
{
"error": "NoDataError",
"code": NO_DATA_ERROR,
"message": "No data was retrieved with the provided input.",
}
)
20 changes: 20 additions & 0 deletions model/ScrapResultLocal.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,18 @@
# = Template Data Types =
# ==============================================
class GenderTemplateDataLocal(BaseModel):
class GenderTemplateDataPoint(BaseModel):
year: int
malePop: int
femalePop: int

metroId: int
localId: int
genderDiversityIndex: float
current: GenderTemplateDataPoint
prev: GenderTemplateDataPoint
meanMalePop: float
meanFemalePop: float


class AgeTemplateDataLocal(BaseModel):
Expand Down Expand Up @@ -53,4 +64,13 @@ class AgeHistogramAreaData(BaseModel):


class PartyTemplateDataLocal(BaseModel):
class PartyCountDataPoint(BaseModel):
party: str
count: int

metroId: int
localId: int
partyDiversityIndex: float
prevElected: list[PartyCountDataPoint]
currentElected: list[PartyCountDataPoint]
currentCandidate: list[PartyCountDataPoint]
18 changes: 18 additions & 0 deletions model/ScrapResultMetro.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,17 @@
# = Template Data Types =
# ==============================================
class GenderTemplateDataMetro(BaseModel):
class GenderTemplateDataPoint(BaseModel):
year: int
malePop: int
femalePop: int

metroId: int
genderDiversityIndex: float
current: GenderTemplateDataPoint
prev: GenderTemplateDataPoint
meanMalePop: float
meanFemalePop: float


class AgeTemplateDataMetro(BaseModel):
Expand Down Expand Up @@ -52,4 +62,12 @@ class AgeHistogramAreaData(BaseModel):


class PartyTemplateDataMetro(BaseModel):
class PartyCountDataPoint(BaseModel):
party: str
count: int

metroId: int
partyDiversityIndex: float
prevElected: list[PartyCountDataPoint]
currentElected: list[PartyCountDataPoint]
currentCandidate: list[PartyCountDataPoint]
55 changes: 55 additions & 0 deletions model/ScrapResultNational.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from pydantic import BaseModel


# ==============================================
# = Template Data Types =
# ==============================================
class GenderTemplateDataNational(BaseModel):
class GenderTemplateDataPoint(BaseModel):
year: int
malePop: int
femalePop: int

genderDiversityIndex: float
current: GenderTemplateDataPoint
prev: GenderTemplateDataPoint


class AgeTemplateDataNational(BaseModel):
class AgeRankingParagraphData(BaseModel):
ageDiversityIndex: float

class AgeIndexHistoryParagraphData(BaseModel):
class AgeIndexHistoryIndexData(BaseModel):
year: int
unit: int
candidateCount: int
candidateDiversityIndex: float
candidateDiversityRank: int
electedDiversityIndex: float
electedDiversityRank: int

mostRecentYear: int
history: list[AgeIndexHistoryIndexData]

class AgeHistogramParagraphData(BaseModel):
year: int
candidateCount: int
electedCount: int
firstQuintile: int
lastQuintile: int

rankingParagraph: AgeRankingParagraphData
indexHistoryParagraph: AgeIndexHistoryParagraphData
ageHistogramParagraph: AgeHistogramParagraphData


class PartyTemplateDataNational(BaseModel):
class PartyCountDataPoint(BaseModel):
party: str
count: int

partyDiversityIndex: float
prevElected: list[PartyCountDataPoint]
currentElected: list[PartyCountDataPoint]
currentCandidate: list[PartyCountDataPoint]
187 changes: 160 additions & 27 deletions routers/ageHist.py
Original file line number Diff line number Diff line change
@@ -1,46 +1,170 @@
from fastapi import APIRouter
from model import BasicResponse, MongoDB
from model.AgeHist import AgeHistDataTypes, AgeHistMethodTypes, MetroAgeHistData
from model.AgeHist import (
AgeHistDataTypes,
AgeHistMethodTypes,
MetroAgeHistData,
NationalAgeHistData,
)


router = APIRouter()
router = APIRouter(prefix="/age-hist", tags=["age-hist"])


@router.get("/age-hist/{metroId}")
@router.get("/")
async def getNationalAgeHistData(
ageHistType: AgeHistDataTypes, year: int, method: AgeHistMethodTypes
) -> BasicResponse.ErrorResponse | NationalAgeHistData:
# histogram = await MongoDB.client.stats_db["age_hist"].find_one(
# {
# "councilorType": "national_councilor",
# "is_elected": ageHistType == AgeHistDataTypes.elected,
# "year": year,
# "method": method,
# }
# )

# if histogram is None:
# return BasicResponse.ErrorResponse.model_validate(
# {
# "error": "NoDataError",
# "code": BasicResponse.NO_DATA_ERROR,
# "message": "No data retrieved with the provided input.",
# }
# )

# return NationalAgeHistData.model_validate({"data": histogram["data"]})
return NationalAgeHistData.model_validate(
{
"data": [
{
"minAge": 21,
"maxAge": 22,
"count": 75,
"ageGroup": 0,
},
{
"minAge": 22,
"maxAge": 23,
"count": 87,
"ageGroup": 1,
},
{
"minAge": 29,
"maxAge": 30,
"count": 104,
"ageGroup": 2,
},
{
"minAge": 45,
"maxAge": 46,
"count": 354,
"ageGroup": 2,
},
{
"minAge": 46,
"maxAge": 47,
"count": 463,
"ageGroup": 3,
},
{
"minAge": 63,
"maxAge": 64,
"count": 240,
"ageGroup": 4,
},
]
}
)


@router.get("/{metroId}")
async def getMetroAgeHistData(
metroId: int, ageHistType: AgeHistDataTypes, year: int, method: AgeHistMethodTypes
) -> BasicResponse.ErrorResponse | MetroAgeHistData:
if (
await MongoDB.client.district_db["metro_district"].find_one(
{"metroId": metroId}
)
is None
):
return BasicResponse.ErrorResponse.model_validate(
{
"error": "RegionCodeError",
"code": BasicResponse.REGION_CODE_ERR,
"message": f"No metro district with metroId {metroId}.",
}
)
# if (
# await MongoDB.client.district_db["metro_district"].find_one(
# {"metroId": metroId}
# )
# is None
# ):
# return BasicResponse.ErrorResponse.model_validate(
# {
# "error": "RegionCodeError",
# "code": BasicResponse.REGION_CODE_ERR,
# "message": f"No metro district with metroId {metroId}.",
# }
# )

histogram = await MongoDB.client.stats_db["age_hist"].find_one(
# histogram = await MongoDB.client.stats_db["age_hist"].find_one(
# {
# "level": 1,
# "councilorType": "metro_councilor",
# "is_elected": ageHistType == AgeHistDataTypes.elected,
# "year": year,
# "method": method,
# "metroId": metroId,
# }
# )

# if histogram is None:
# return BasicResponse.ErrorResponse.model_validate(
# {
# "error": "NoDataError",
# "code": BasicResponse.NO_DATA_ERROR,
# "message": "No data retrieved with the provided input.",
# }
# )

# return MetroAgeHistData.model_validate(
# {"metroId": metroId, "data": histogram["data"]}
# )
return MetroAgeHistData.model_validate(
{
"level": 1,
"councilorType": "metro_councilor",
"is_elected": ageHistType == AgeHistDataTypes.elected,
"year": year,
"method": method,
"metroId": metroId,
"data": [
{
"minAge": 21,
"maxAge": 22,
"count": 75,
"ageGroup": 0,
},
{
"minAge": 22,
"maxAge": 23,
"count": 87,
"ageGroup": 1,
},
{
"minAge": 29,
"maxAge": 30,
"count": 104,
"ageGroup": 2,
},
{
"minAge": 45,
"maxAge": 46,
"count": 354,
"ageGroup": 2,
},
{
"minAge": 46,
"maxAge": 47,
"count": 463,
"ageGroup": 3,
},
{
"minAge": 63,
"maxAge": 64,
"count": 240,
"ageGroup": 4,
},
],
}
)

return MetroAgeHistData.model_validate(
{"metroId": metroId, "data": histogram["data"]}
)


@router.get("/age-hist/{metroId}/{localId}")
@router.get("/{metroId}/{localId}")
async def getLocalAgeHistData(
metroId: int,
localId: int,
Expand Down Expand Up @@ -74,6 +198,15 @@ async def getLocalAgeHistData(
}
)

if histogram is None:
return BasicResponse.ErrorResponse.model_validate(
{
"error": "NoDataError",
"code": BasicResponse.NO_DATA_ERROR,
"message": "No data retrieved with the provided input.",
}
)

return MetroAgeHistData.model_validate(
{"metroId": metroId, "localId": localId, "data": histogram["data"]}
)
Loading

0 comments on commit f1857cd

Please sign in to comment.