파이널 프로젝트
LCK 커뮤니티 loco.gg
프로젝트 기간 2023.7.11 ~ 2023.8.17
팀 인원 : 6명
1. lolco.gg 란?
LOLCO.GG는 국내에서 개최 중인 리그 오브 레전드 e스포츠 대회 – 2023 LCK (League of Legends Champions Korea)와 관련된 경기 정보, 승부 예측 및 커뮤니티 서비스를 제공하는 웹 애플리케이션입니다. 매일 LCK 경기 결과가 업데이트되며, 대회 정보 외에도 LOLCO.GG에서만 즐길 수 있는 카드 컬렉션, 스토어, 선택지 게임 등 다양한 즐길 거리가 소환사님을 기다리고 있습니다
2. 기획의도
- LCK 를 좋아하는 사람들을 위해 LCK 전용 놀이터를 만들어보자 라는 생각에 기획하게 되었습니다.
- LCK 경기를 보면서 사람들이 어느 팀이 이길까? 어느팀이 승리할지 내기를 하면서 보는 경우가 많은데
- 그런 예측 이벤트는 모든 경기를 하는 게 아니라 이벤트성으로 하는 경우가 많아 승부예측 전용 사이트를 만들어보는 게 어떨까?라는 생각에
- 사이트를 구축하게 되었습니다. 승부예측만이 아니라 선수를 좋아하는 사람들을 위해 예측을 통해 얻을 수 있는 포인트와 각종 이벤트 포인트로
- 선수 전용 카드와 간단하게 즐길 수 있는 오락거리등등 회원이 쉽게 접할 수 있는 사이트입니다.
3. ERD
기능 정의서가 완성된 후 바로 ERD를 만들기로 했다 세미때와 똑같이 ERD클라우드를 이용하기로 했다.
다들 각자가 맡은 기능을 ERD에 작성하기로 했고 내가 ERD를 마지막으로 취합 및 정리하는 일을 맡았다.
2번째로 하는 프로젝트라 그런지 훨씬 수월했다.
4. 화면설계
화면설계를 세미프로젝트에서 시간을 굉장히 많이 잡아먹어서 어떻게 하면 더효율적으로 화면설계를 하고 빠르게 끝낼 수 있을까? 고민을 했다. 그러다 피그마와 VSCODE에 연동되는 플러그인 있다고 해서 그걸 사용하기로 했다.
플러그인을 사용하니 화면설계의 시간이 정말 많이 줄었고 신경 쓸 것도 많이 줄어서 굉장히 유용하게 사용했다.
이번 파이널을 화면보다 기능 쪽에 집중하기 위해 이쁘게 만들자 라는 생각을 어느 정도 접어두고 만들었다.
그리고 디자인 쪽을 맡은 팀원들이 우리끼리 쓸 공통적인 css탬플릿을 만들어서 사용했는데 그거 덕분에 더욱 빠르게 화면설계를 마칠 수가 있었다.
5. 기능구현
내가 맡은 기능 : 커뮤니티게시판, 공지사항, 카드, 신고관리
커뮤니티
1. 실시간 인기글, 주간 인기글
- 실시간인기글은 최근 24시간 기준으로 가장 많은 조회수를 가진 게시글부터 보이게 했고
- 주간 인기글을 최근 일주일기준으로 조회수가 많은 게시글이 보이게 했다.
2. 게시글 작성
게시글 작성 기능은 TOAST 에디터를 사용해서 작성기능을 만들었다.
동영상 도 첨부할 수 있는데 유튜브 영상만 가능하다.
3. 게시글 목록
게시글은 인기글과 최신순을 볼 수가 있고 카테고리에 따라서 인기글과 최신순을 볼수도 있다.
4. 게시글상세
게시글상세에서는 게시글에 추천과 비추천을 줄 수가 있고 신고 및 공유를 할 수가 있다.
5. 댓글
댓글을 작성할 때 사용자가 가지고 있는 이모티콘을 사용해서 댓글을 달수가 있고 수정 및 삭제가 가능하다
대댓글을 본댓글에만 가능하다. 댓글도 추천 및 비추천이 가능하다 본댓글이 삭제되면 대댓글도 삭제된다.
공지사항
1. 공지사항 메인
공지사항 메인에서는 각종 카테고리별 공지사항을 한 번에 볼 수가 있다.
작성은 관리자만 가능하고 관리자 로그인 시에만 작성버튼이 활성화된다.
관리자만이 수정 및 삭제가 가능하다.
카드 페이지
1. 나의 카드 페이지
나의 카드페이지에서는 자신이 가지고 있는 카드 전체를 볼 수가 있고
대표 카드를 설정해서 볼 수가 있다.
2. 카드 카탈로그
카드 카탈로그는 모든 카드를 볼 수 있는 페이지다.
등급별 팀별 선수별 포지션별로 검색할 수 있고 선수 이름으로도 검색이 가능하다.
3. 카드 업적
카드업적은 자신이 업적에 맡는 카드를 가지고 있다면 조건에 부합하는 업적의 칭호 보상을 받을 수 있는 사이트이다.
자신이 가지고 있는 카드는 노란색 테두리로 활성화된다.
카테고리를 통해 달성한 업적과 미달성업적을 볼 수가 있다.
신고페이지
1. 게시글 댓글 신고관리
게시글신고와 댓글신고를 받고 횟수가 3회 이상이 된다면 게시글, 댓글을 삭제할 수 있다.
아쉬운 점
1. AI 승부예측
처음에 어떤 기능들을 넣을까 고민을 많이 했다. 그러다 유튜브영상에서 ai영상을 보게 되었는데
그때 문득 떠올랐다 승부예측이니 간 ai가 승부예측을 하고 회원과 대결하는 그런 기능이 있으면 어떨까?라는 생각을 했다.
그래서 ai승부예측에 대한 자료들을 수집하기로 했다. 다행히 ai승부예측에 대한 정보들은 많이 있었고
그런 프로젝트도 많았다 하지만 한 가지 문제점은 거의 파이썬으로 이루어져 있다는 거다.
지금까지 java 만 배웠기 때문에 지금 파이썬을 새로 배워서 내가 프로젝트에 적용할 수 있을까?라는 생각이 들었고
주말 동안 한번 해보자 하고 자료들을 수집하며 만들어봤지만 이건 안될 거 같다는 생각이 들어 포기했다..
2. 카드게임
카드 페이지를 만들 때 처음에 계획한 건 카드게임도 추가할 예정이었지만
프로젝트를 진행하다 게시판에서 생각보다 많은 시간이 허비되어서 카드 수집 페이지와 업적만 페이지만만 들고 카드게임을 만들지 못했다..
카드페이지를 보면 각각 카드마다 개인 능력치가 전부 다른 걸 볼 수 있다.
크롤링을 통해 lck spring 시즌 선수 성적데이터를 가져와서 각자의 선수능력치를 만들었는데
이걸 만든 이유가 선수 카드게임을 만들기 위해 스텟을 추가한 것이다..
하지만 커뮤니티페이지에서 생각보다 오랜 시간을 허비했기에 카드게임까지 만들다간 기간 안에 전부 기능을 만들지 못한다는 생각에 과감히 포기해 버렸다 이 부분은 너무나 아쉬웠다..
package gg.lolco.controller;
import java.io.IOException;
import java.util.Map;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import gg.lolco.model.service.SampleService;
@Controller
public class SampleController {
private final SampleService service;
public SampleController(SampleService service) {
this.service = service;
}
@GetMapping("/sampleAll")
public String selectAll(Model model) {
model.addAttribute("sample", service.selectAll());
return "sample/sampleList";
}
@GetMapping("/playerinsert")
public String playerinsert() {
final String stockList = "https://lol.fandom.com/wiki/Special:RunQuery/TournamentStatistics?TS%5Bpreload%5D=TournamentByPlayerRole&TS%5Brole%5D=Support&TS%5Btournament%5D=LCK%2F2023+Season%2FSpring+Season&_run=";
Connection conn = Jsoup.connect(stockList);
try {
Document document = conn.get();
Elements stockTableBody = document.select(".wikitable tr .spstats-team");
for (Element element : stockTableBody) {
String team=element.select("a").attr("title");
String name = element.siblingElements().get(0).text();
double attack = Double.parseDouble(element.siblingElements().get(5).text());
double defense = Double.parseDouble(element.siblingElements().get(6).text()) + 0.01; // Add a small constant to avoid divide-by-zero
double assistant = Double.parseDouble(element.siblingElements().get(7).text());
double survival = Double.parseDouble(element.siblingElements().get(8).text());
double growth = Double.parseDouble(element.siblingElements().get(11).text());
PlayerStats playerAttack = new PlayerStats(0, 1.5, 0, 100);
PlayerStats playerDefense = new PlayerStats(3.5, 1.1, 0, 100);
PlayerStats playerAssistant = new PlayerStats(0, 10.9, 0, 100);
PlayerStats playersSurvival = new PlayerStats(0, 7.7, 0, 100);
PlayerStats playersGrowth = new PlayerStats(6, 9, 0, 100);
double scaledValueAttack = playerAttack.scaleValue(attack);
double scaledValueDefense = playerDefense.scaleValue(defense);
double scaledValueAssistant = playerAssistant.scaleValue(assistant);
double scaledValueSurvival = playersSurvival.scaleValue(survival);
double scaledValueGrowth = playersGrowth.scaleValue(growth);
String season="LCK 2023 spring";
double a =(Math.round(scaledValueAttack)+6);
double d =(Math.round(scaledValueDefense)+6);
double s =(Math.round(scaledValueAssistant)+6);
double u =(Math.round(scaledValueSurvival)+6);
double g =(Math.round(scaledValueGrowth)+6);
String position="SUP";
System.out.println(position);
Map<String,Object> param =Map.of("name",name,"season",season,"attack",a,"defense",d,"assistant",s,"survival",u,"growth",g,"position",position,"team",team);
int playerInsertTop=service.playerInsertTop(param);
}
} catch (IOException ignored) {
}
return "template";
}
}
위에는 크롤링을 통해 선수카드에 능력치를 넣는 코드다..