0. 서론
이제 이를 바탕으로 내가 이 데이터를 db에 저장하고 업데이트 함으로써 사용자에게 원하는 시간에 효율을 보여줘야합니다. Lostark API 데이터를 활용하여, 생활재료(고고학)을 이용한 특정 재료의 제작 비용과 수수료에 따른 수익을 계산하는 기능을 구현하려고합니다.
1. 데이터 수집
def fetch_material_prices(request):
load_dotenv()
# 환경 변수에서 토큰 가져오기
Token = os.getenv('LOSTARK_API_TOKEN')
headers = {
'accept': 'application/json',
'authorization': f'Bearer {Token}', # 여기에 실제 API 토큰 입력
'Content-Type': 'application/json',
}
# 필요한 재료와 그들의 카테고리 코드
materials = [
{"ItemName": "고대 유물", "CategoryCode": 90700},
{"ItemName": "희귀한 유물", "CategoryCode": 90700},
{"ItemName": "오레하 유물", "CategoryCode": 90700},
{"ItemName": "아비도스 유물", "CategoryCode": 90700},
{"ItemName": "아비도스 융화 재료", "CategoryCode": 50010},
{"ItemName": "최상급 오레하 융화 재료", "CategoryCode": 50010},
]
for material in materials:
json_data = {
'Sort': 'GRADE',
'CategoryCode': material["CategoryCode"],
'ItemName': material["ItemName"],
'PageNo': 0,
'SortCondition': 'ASC',
}
response = requests.post('https://developer-lostark.game.onstove.com/markets/items', headers=headers, json=json_data)
if response.status_code == 200:
data = response.json().get('Items', [])
if data:
item = data[0] # 첫 번째 아이템 정보만 저장
Material.objects.update_or_create(
name=item["Name"],
defaults={
'icon_url': item["Icon"],
'bundle_count': item["BundleCount"],
'yday_avg_price': item["YDayAvgPrice"],
'recent_price': item["RecentPrice"],
'current_min_price': item["CurrentMinPrice"],
},
)
return redirect(reverse('calculate_profit'))
(1) 우리가 원하는 데이터의 가격들을 불러와야합니다.
(2) env토큰을 불러옴으로써 다른 사용자가 내 토큰값을 알수 없게 합니다.
(3) api에서 요구하는 header에 맞게 작성해줍니다.
(4) 내가 원하는 데이터의 가격과 코드를 앞서서 알아냈으니 이제 이를 바탕으로 정보를 받아와야합니다. 저는 총 6개의 재료를 필요로 했습니다.
(5) api요청을 보내고 응답데이터를 파싱합니다.
(6) 이 코드를 통해 재료데이터를 실시간으로 관리하는데 역할을 맡고 있으며, 프로젝트의 기본이 되는 구조입니다.
2. 효율 계산
def calculate_profit(request):
last_updated = Material.objects.aggregate(Max('updated_at'))['updated_at__max']
last_updated_formatted = last_updated.strftime("%m/%d %H:%M") if last_updated else "갱신 기록 없음"
if request.method == 'GET':
return render(request, 'lostark_market/calculate.html')
if request.method == 'POST':
discount = float(request.POST.get('discount', 0)) / 100 # 기본값: 0% 수수료 감소
# 체크박스 값 처리
exclude_ancient = 'exclude_ancient' in request.POST
exclude_rare = 'exclude_rare' in request.POST
exclude_oreha = 'exclude_oreha' in request.POST
exclude_abidos = 'exclude_abidos' in request.POST
# 필요한 재료 정보
try:
materials = {
'고대 유물': Material.objects.get(name="고대 유물"),
'희귀한 유물': Material.objects.get(name="희귀한 유물"),
'오레하 유물': Material.objects.get(name="오레하 유물"),
'아비도스 유물': Material.objects.get(name="아비도스 유물"),
}
abidos_crafted = Material.objects.get(name="아비도스 융화 재료")
oreha_crafted = Material.objects.get(name="최상급 오레하 융화 재료")
except Material.DoesNotExist:
return render(request, 'lostark_market/error.html', {'message': '필요한 재료 데이터가 없습니다.'})
# 제작 정보
crafted_items = [
{
'name': '아비도스 융화 재료',
'needed_materials': {
'고대 유물': 86 if not exclude_ancient else 0,
'아비도스 유물': 33 if not exclude_abidos else 0,
'희귀한 유물': 45 if not exclude_rare else 0,
},
'crafting_fee': 400,
'selling_price': abidos_crafted.current_min_price,
'produced_quantity': 10,
'icon_url': abidos_crafted.icon_url,
},
{
'name': '최상급 오레하 융화 재료',
'needed_materials': {
'고대 유물': 107 if not exclude_ancient else 0,
'오레하 유물': 52 if not exclude_oreha else 0,
'희귀한 유물': 51 if not exclude_rare else 0,
},
'crafting_fee': 300,
'selling_price': oreha_crafted.current_min_price,
'produced_quantity': 15,
'icon_url': oreha_crafted.icon_url,
},
]
results = []
# 각 제작 아이템에 대해 계산
for item in crafted_items:
total_cost = 0
for material_name, quantity in item['needed_materials'].items():
material = materials[material_name]
price_per_unit = material.recent_price / material.bundle_count
total_cost += quantity * price_per_unit
# 제작 수수료 계산
crafting_fee = item['crafting_fee'] * (1 - discount)
total_cost += crafting_fee
# 1개당 제작 비용
cost_per_unit = total_cost / item['produced_quantity']
# 경매장 수수료 계산
auction_fee = math.ceil(item['selling_price'] * 0.05)
final_amount = item['selling_price'] - auction_fee
# 이득/손해 계산
profit_per_unit = final_amount - cost_per_unit
results.append({
'name': item['name'],
'icon_url': item['icon_url'], # 여기서 가져오는 값이 올바른지 확인
'total_cost': round(total_cost, 2),
'cost_per_unit': round(cost_per_unit, 2),
'selling_price': round(item['selling_price'], 2),
'auction_fee': round(auction_fee, 2),
'final_amount': round(final_amount, 2),
'profit_per_unit': round(profit_per_unit, 2),
'produced_quantity': item['produced_quantity'],
})
# 재료 데이터 추가
material_info = [
{
'name': material.name,
'icon_url': material.icon_url,
'recent_price': material.recent_price,
'bundle_count': material.bundle_count,
'price_per_unit': round(material.recent_price / material.bundle_count, 2),
}
for material in materials.values()
]
return render(request, 'lostark_market/result.html', {
'results': results,
'material_info': material_info,
'last_updated': last_updated_formatted, # 템플릿에 전달
})
(1) 기존에 Material 모델의 데이터가 없으면 저장을 있다면 새로 덮어씌우도록합니다.
(2) get요청을 받으면 계산페이지를 랜더링합니다. 주로 처음 방문한 사용자를 위해 실행합니다.
(3) post요청을 통해 사용자가 업데이트 버튼을 클릭시 실행합니다.
(4) 본인이 제작에 사용되는 특정재료(고급유물 등)과 같은 것을 가지고 있을 경우를 대비해서 이를 제외시키고 계산하도록하는 코드를 넣습니다.
(5) materials 를 통해 데이터 베이스에 저장된 재료를 가져옵니다.
(6) crafted_item을 통해 제작에 필요한 물품과 개수를 설정합니다. 이는 변하지 않는 값이기에 절대값으로 지정해줍니다.
(6-2) 체크박스가 되어있다면 필요개수를 0으로 설정해서 계산에서 제외합니다.
(7) for 구문을 통해 제작비용과 수수료와 같은 손익을 계산하는 과정을 넣습니다.
(8) material_info를 통해 필요한 정보를 템플릿에 전달하도록 합니다.
(9) 이 모든 계산결과와 8에서 작성한 정보를 템플릿에 전달합니다.
3. 결과
3-1) 계산 전

# 이를 통해 본인이 가지고있는 재료들을 체크박스를 통해 제외하고 계산할 수 있도록 하였습니다.
3-2) 계산 후

# 이런식으로 제작시 필요 가격을 보여주고 이를 경매장에 판매시 본인의 수익을 보여줌으로써 이 프로젝트의 완성을 알려줍니다.
3-3) 배포
(1) AWS EC2 배포를 진행하였습니다.
(2) EC2 인스턴스 생성을 통해 Ubuntu 를 선택하였습니다. (많은 블로그 참조)
(3) EC2 SSH 를 로컬에서 연결후
(4) 깃허브의 프로젝트 코드를 클론 한 뒤에 DJANGO 설정에서 도메인을 지정해 주었습니다. (도메인은 무료도메인사이트 이용하였습니다)
(5) django서버를 노출하지 않게하기 위해 Nginx를 통해 간단한 배포를 목표로 하였습니다.
(6) 약 하루정도 배포하고 문제없이 작동한 것을 확인하고 이를 종료 하였습니다.
4. 후기
처음으로 aws를 통해 배포를 진행하였습니다. 에러도 많이나고 코드 작성할때 많은 문구가 들어가서 힘들었지만 저만의 목표인 api를 통해 이를 python django틀에 맞게 고쳐서 효율을 계산하는 과정을 거치도록하는걸 보여줬다고 생각하였습니다. 끝!
'Django 개인프로젝트 > 두번째 프로젝트' 카테고리의 다른 글
| 1. LostarkAPI를 이용한 미니 프로젝트 (0) | 2024.11.27 |
|---|