신기성

필요없는 부분 삭제

1 -
2 -var readline=require('readline');//입력받기 위한 모듈
3 -var r=readline.createInterface({input:process.stdin,output:process.stdout});//키보드 입출력 정의
4 -var rtfw1="http://www.rankedftw.com/search/?name=";//rtfw에서 기본 검색 url
5 -var rtfw2="http://www.rankedftw.com/player/"//rtfw 번호 기반 특정 플레이어 검색 url
6 -var league='silver_2';
7 -var region='KR';
8 -//
9 -var cheerio=require('cheerio');//cheerio모듈 사용
10 -var request=require('request');//request모듈 사용
11 -var fs=require('fs');//파일시스템 사용
12 -//
13 -//request 1 variable
14 -var username='';//username문자열 선언
15 -var userleague='';//userleague 문자열 선언
16 -var userregion='';//userregion 문자열 선언
17 -var usernumber='';//usernumber 문자열 선언
18 -//
19 -//request 2 variable
20 -
21 -//
22 -//request 3-1 variable
23 -
24 -//
25 -//request 3-2 variable
26 -
27 -//
28 -//request 3-3 variable
29 -
30 -//
31 -//system message
32 -
33 -//
34 -//delivering variable
35 -var momentum;//기세
36 -var terran_proficiency;//테란 숙련도
37 -var zerg_proficiency;//저그 숙련도
38 -var protoss_proficiency;//프로토스 숙련도
39 -var primary_race;//주 종족
40 -var win_rate;//시즌 전체 승률
41 -
42 -var myrace;//내 종족
43 -var enemyrace;//상대 종족
44 -var recommend;//추천빌드(운영/타이밍/올인)
45 -//
46 -
47 -r.question("분석을 원하는 아이디를 입력하세요 : ",function(answer){//question메소드에서 callback함수 생성
48 - //question은 에러 제어 만들면 안된다.
49 - console.log("r.question processing");//callback함수란 이벤트가 왔을 때 실행되는 함수이다. answer에 검색을 원하는 아이디가 담겨있다.
50 - rtfw1=rtfw1+answer;//검색 url 구성
51 - console.log(rtfw1);//테스트용 : 검색 url 확인
52 -//
53 -request(rtfw1,(error,response,body)=>{//rtfw url 불러오기 request 1
54 - if(error){throw error};//에러처리
55 - console.log("request 1 processing");
56 - let $ = cheerio.load(body);//rtfw가 body이다. $로 jquery방식으로 html탐색
57 - $('ul').find('a').each(function(index,elem){//ul 태그 아래 a태그를 찾는다.
58 - username=$(this).find('.name').text().trim();//name클래스를 찾아 공백빼고 텍스트화
59 - userleague=$(this).find('.league').text().trim();//league클래스를 찾아 공백빼고 텍스트화
60 - userregion=$(this).find('.region').text().trim();//region클래스를 찾아 공백빼고 텍스트화
61 - if((username===answer)&&(userregion===region)){//아직 리그 구현 안함-리그는 그림으로 비교
62 - console.log(`${username}`);//테스트용 : 유저네임 출력
63 - console.log(`${userregion}`);//테스트용 : 유저리전 출력
64 - var usernumber=$(this).toString().slice(29,43);//rtfw에서 사용하는 사용자번호를 문자열로 넉넉히 자름
65 - var localindex1=usernumber.search('/');//첫번째 슬레시 발견하는 인덱스 검출
66 - usernumber=usernumber.slice(localindex1+1);//앞부분 슬래시 자른다.
67 - var localindex2=usernumber.search('/')-localindex1+1;//두번째 슬레시 발견하는 인덱스 검출
68 - usernumber=usernumber.slice(0,localindex2);//뒷부분 슬래시 자른다.
69 - console.log(`${usernumber}`);//테스트용 : 유저넘버 출력
70 - if(rtfw2.length>33){//하나라도 붙어있으면
71 - rtfw2=rtfw2;//아무것도 안한다.
72 - }else{//그렇지않고 아무것도 안붙어있으면
73 - rtfw2=rtfw2+usernumber+'/';//rtfw2 url갱신
74 - }
75 - console.log(rtfw2);//테스트용 : rtfw2 출력
76 - }//이름서버리그비교if종료
77 - });//ul a find문 종료
78 -
79 - var profileID='';
80 - request(rtfw2,(error,response,body)=>{//rtfw2 url 불러오기 request 2
81 - if(error){throw error};//에러처리
82 - console.log('request2 processing');//테스트용 : request2 실행여부 출력
83 - let $ = cheerio.load(body);//rtfw2가 body이다. $로 jquery방식으로 html탐색
84 - $('.content').find('.bnet-link').each(function(index,elem){//content 클래스 안의 bnet-link클래스를 포함하는 요소를 찾는다.
85 - profileID=$(this).toString().slice(62,72);//얻고자 하는 profileID를 포함하여 앞뒤로 적당히 자른다.
86 - var localindex3=profileID.search('/');//첫번째 슬레시 발견하는 인덱스 검출
87 - profileID=profileID.slice(localindex3+1);//앞부분 슬래시 자른다.
88 - var localindex4=profileID.search('/')-localindex3;//두번째 슬레시 발견하는 인덱스 검출
89 - profileID=profileID.slice(0,localindex4);//뒷부분 슬래시 자른다.
90 - console.log(`${profileID}`);//테스트용 : profileID 출력
91 - });//a bnetlink 종료
92 -//console.log(`${profileID}`);//테스트용 : profileID 출력
93 -
94 -var match_history_1="https://kr.api.blizzard.com/sc2/legacy/profile/3/1/"//매치히스토리 url 앞부분
95 -var match_history_2="/matches?access_token=US0q3wV6W1fIYZmRnEBbNvUrRHYZhwANIi"//매치히스토리 url 뒷부분
96 -var match_history_url=match_history_1+profileID+match_history_2;//매치히스토리 url 구성
97 -console.log(match_history_url);//테스트용 : 매치히스토리 url 출력
98 -
99 -request(match_history_url,(error,response,body)=>{//match history request request 3
100 - if(error){throw error};//에러처리
101 - console.log('request3 processing');//테스트용 : request 작동여부 출력
102 -
103 -var obj1=JSON.parse(body);//request 결과를 JSON object로 변환
104 -//console.log(obj.matches [0].map);//테스트용 : 하나에 접근
105 -$(obj1.matches).each(function(index,match){//body에서 각각의 배열요소 match들과 인덱스 사용
106 - if(match.type=='1v1'){//경기타입이 1대1인 경우에만 관심있다.
107 - console.log(index+":::",match.decision,match.map);//인덱스와 승패, 맵 표시
108 -};//if 1v1 종료
109 -});//each function 종료
110 -
111 -var ladder_1="https://kr.api.blizzard.com/sc2/legacy/profile/3/1/"
112 -var ladder_2="/ladders?access_token=US0q3wV6W1fIYZmRnEBbNvUrRHYZhwANIi";
113 -var ladder_url=ladder_1+profileID+ladder_2;
114 -console.log(ladder_url);
115 -request(ladder_url,(error,response,body)=>{//ladder request request 4
116 - if(error){throw error};
117 - console.log('request4 processing');
118 - var obj2=JSON.parse(body);//request 결과를 JSON object로 변환
119 -// console.log(obj2.currentSeason [2].ladder[0].wins);//테스트용 : 하나에 접근
120 - var wins=obj2.currentSeason[2].ladder[0].wins;
121 - var losses=obj2.currentSeason[2].ladder[0].losses;
122 -win_rate=wins/(wins+losses);
123 - //console.log(wins);
124 - //console.log(losses);
125 - //console.log(win_rate);
126 -
127 -var profile_1="https://kr.api.blizzard.com/sc2/legacy/profile/3/1/";
128 -var profile_2="?access_token=US0q3wV6W1fIYZmRnEBbNvUrRHYZhwANIi";
129 -var profile_url=profile_1+profileID+profile_2;
130 -console.log(profile_url);
131 -request(profile_url,(error,response,body)=>{//profile request request 5
132 - if(error){throw error};
133 - console.log('request5 processing');
134 - var obj3=JSON.parse(body);//request 결과를 JSON object로 변환
135 - //console.log(obj2.currentSeason [1].ladder[0].wins);//테스트용 : 하나에 접근
136 -primary_race=obj3.career.primaryRace;
137 - //console.log(primary_race);
138 - var terran_level=obj3.swarmLevels.terran.level;
139 - var zerg_level=obj3.swarmLevels.zerg.level;
140 - var protoss_level=obj3.swarmLevels.protoss.level;
141 -
142 - //console.log(terran_level);
143 - //console.log(zerg_level);
144 - //console.log(protoss_level);
145 -
146 -//build recommend algorithm
147 -var matchresults=[];//매치결과 담을 배열 선언
148 -var momentum_win=0;//최근 10경기 중 승수 초기화
149 -for (var i=0;i<25;i++){//매치히스토리는 최대 25개
150 - if(obj1.matches[i].type=='1v1'){//1v1에만 관심있다.
151 - matchresults.push(obj1.matches[i].decision);//배열 끝에 결과 삽입
152 - if((matchresults.length<11)&&(obj1.matches[i].decision=='Win')){//최근 10경기에서 승리한 경우
153 - momentum_win=momentum_win+1;//그 승수를 카운트한다.
154 - }//if length11 종료
155 -}//obj1 1v1 종료
156 -}//for i 25 종료
157 -//console.log(matchresults);//테스트용 : matchresults 출력
158 -//console.log(momentum_win);//테스트용 : momentum_win 출력
159 -if(momentum_win>=7){//7승 이상이면 상승세
160 -momentum='상승세';
161 -}
162 -if((momentum_win<7)&&(momentum_win>=4)){//4승이상 7승미만이면 정체
163 -momentum='정체중';
164 -}
165 -if(momentum_win<4){//4승 미만이면 하락세
166 -momentum='하락세';
167 -}
168 -//console.log(momentum);//테스트용 : 기세 출력
169 -
170 -if(terran_level<50){//테란 레벨 50 안되면
171 - terran_proficiency='비숙련자'//테란 비숙련자
172 -} else{
173 - terran_proficiency='숙련자'
174 -}
175 -if(zerg_level<50){//저그 레벨 50 안되면
176 - zerg_proficiency='비숙련자'//저그 비숙련자
177 -} else{
178 - zerg_proficiency='숙련자'
179 -}
180 -if(protoss_level<50){//프로토스 레벨 50 안되면
181 - protoss_proficiency='비숙련자'//프로토스 비숙련자
182 -} else{
183 - protoss_proficiency='숙련자'
184 -}
185 -//
186 -//system message part
187 -console.log("최근 10경기 분석 결과 현재 상대는 '"+momentum+"'입니다.");
188 -console.log("상대는 테란 '"+terran_proficiency+"'입니다.");
189 -console.log("상대는 저그 '"+zerg_proficiency+"'입니다.");
190 -console.log("상대는 프로토스 '"+protoss_proficiency+"'입니다.");
191 -console.log("상대의 주 종족은 '"+primary_race+"'입니다.");
192 -console.log("상대의 이번 시즌 전체 승률은 '"+win_rate+"'입니다.");
193 -//
194 -//build recommend command
195 -
196 -//
197 -
198 -console.log('request5 done');
199 -});//request5종료
200 -console.log('request4 done');
201 -});//request4종료
202 -console.log('request3 done');
203 -});//request3종료
204 -console.log('request2 done');
205 -});//request2종료
206 -console.log('request1 done');
207 -});//request1 종료
208 -
209 -console.log('r.question done');
210 -//console.log(terran_level);
211 -r.close()//반드시 close를 해줘야 한다.사용이 다 끝난 후에.
212 -});//r.question 끝
1 -/*
2 -var fs = require('fs');//파일 시스템
3 -var readline=require('readline')//readline 모듈
4 -var file = 'target.txt';//파일은 타겟.텍스트이다.
5 -var r=readline.createInterface({
6 - input:process.stdin, output:process.stdout
7 -});//입출력 정의
8 -
9 -
10 -
11 -fs.open(file, 'r+', function(err,fd){//파일을 읽쓰 모드로 열고 없으면 에러발생
12 - if (err) throw err;
13 - console.log('target open complete');//열고 출력
14 - r.question("검색을 원하는 아이디를 입력하세요 : ",function(input){
15 - console.log("입력완료",input);
16 - r.close()
17 - fs.writeFile('target.txt',input,'utf8',function(error){
18 - console.log('writing done')
19 - })
20 - })
21 -})
22 -*/
1 -[object Object]
...\ No newline at end of file ...\ No newline at end of file
1 -사용자가 검색할 아이디를 입력한다.
2 -검색한 아이디를 바탕으로 주소를 만들 텍스트 파일을 생성한다.
3 -텍스트 파일의 내용을 주소로 사용한다.
4 -sc2 API를 가져온다.
5 -sc2 프로필 페이지를 크롤링한다.
6 ---알고리즘에 사용
...\ No newline at end of file ...\ No newline at end of file
1 -1. 사이트 접속
2 -2. 사용자의 서버/리그 설정(래더에서 만난다 가정)
3 -3. 상대 아이디 검색
4 -4. rankedftw에서 해당 아이디로 검색
5 -5. profileID 추출
6 -6. profileID로 API에서 정보 추출
7 -7. profileID로 profile페이지에서 정보 추출(필요하면)
8 -8. 알고리즘에 사용
9 -9. 추천빌드 출력
...\ No newline at end of file ...\ No newline at end of file
1 -1. 검색할 아이디를 입력받는다. :done ->서버,리그 선택으로 심화
2 -2. rtfw에서 검색한다.
3 -3. rtfw에서 찾는다. -> 전체 페이지로 심화
4 -4. 리스트를 클릭한다.
5 -5. a.player에서 profileID를 추출한다. ->플레이어 페이지나 프로필 페이지 등등 활용 가능
6 -6. profileID로 API에서 필요정보 요청
7 -
8 -주의사항 : 한명을 특정해야함. 특정번호는 꼭 7자리가 아닐수 있다. 맨 처음 뜬 사람 기준
9 -없애야 할 철자 : y e r / " 5가지
10 -추가구현사항 : 전체페이지검색, 한글검색
11 -중요포인트 : 편법도 아니고 15초안에 제공가능하다는점!
12 -주종족 추가됨. url에 region realm
13 -최근 5경기 결과로 상승세를 추정
14 -최근 25경기 결과로 승률 50퍼가 넘는 맵 추정
15 -종족레벨 50이 안되면 해당 종족 비숙련자
16 -그냥 정보:이번시즌 전체승률, 주종족
17 -파기정보 : 종족별 승수
18 -
19 -< API를 통해 가져올 수 있는 데이터 >
20 -
21 -1. 최근 이겼는지 졌는지
22 -2. 맵
23 -3. 종족 레벨
24 -4. 이번 시즌 전체 승률
25 -5. 종족별 승수
26 -
27 -6. 주 종족
1 -<추가 구현 사항>
2 --rtfw 다음페이지 검색
3 --rtfw 한글검색 utf8
4 --리그/region/realm 선택
5 -
6 --처리순서 정리
7 -
8 -<정보>
9 -상대 기세 : 최근 래더 10경기 결과로 추정(7승이상:상승,4-7승:평온,3승이하:하락)
10 -//맵별 승률 : 최근 래더 25경기 결과로 승률 50퍼센트가 넘는 맵 추정
11 -종족별 숙련도 : 종족레벨 50 미만일경우 비숙련자
12 -주 종족 : 직접접근
13 -이번시즌 전체 승률 : 승패에 직접접근하여 계산
14 -
15 -<빌드추천 기준>
16 -하락세or비숙련자-운영
17 -상승세or숙련자-올인
18 -비등or이외-타이밍
19 -
20 -<프로젝트 설명>
21 -편법 아니고 빠른시간에 제공가능하다는 점 부각
22 -리그시스템상 승률은 50퍼센트로 수렴한다. 기세로 판단하는 것이 올바르다.
23 -
24 -<발견현상>
25 --API의 json배열이 어느시점부로 바뀌는 현상(ladders에서)
26 --김대엽 선수가 자꾸 움직임;
27 -
28 -<노하우>
29 --request 병렬처리되니까 마트료시카처럼 안쪽에 넣어야 순서대로 처리 가능
1 module.exports = function(app,fs) 1 module.exports = function(app,fs)
2 { 2 {
3 app.get('/',function(req,res){ 3 app.get('/',function(req,res){
4 - var test='333333333333'; 4 +res.render('index',{top: '상대 정보를 입력해 주세요.',
5 -res.render('index',{length: test}); 5 +ejs_momentum: ' ',
6 - 6 +ejs_terran_proficiency: ' ',
7 - 7 +ejs_zerg_proficiency: ' ',
8 +ejs_protoss_proficiency: ' ',
9 +ejs_primary_race: ' ',
10 +ejs_win_rate: ' '});
8 }); 11 });
9 12
10 -app.get('/build/create',function(req,res,next){ 13 +app.get('/recommend',function(req,res,next){
11 14
12 15
13 var readline=require('readline');//입력받기 위한 모듈 16 var readline=require('readline');//입력받기 위한 모듈
14 var r=readline.createInterface({input:process.stdin,output:process.stdout});//키보드 입출력 정의 17 var r=readline.createInterface({input:process.stdin,output:process.stdout});//키보드 입출력 정의
15 var rtfw1="http://www.rankedftw.com/search/?name=";//rtfw에서 기본 검색 url 18 var rtfw1="http://www.rankedftw.com/search/?name=";//rtfw에서 기본 검색 url
16 var rtfw2="http://www.rankedftw.com/player/"//rtfw 번호 기반 특정 플레이어 검색 url 19 var rtfw2="http://www.rankedftw.com/player/"//rtfw 번호 기반 특정 플레이어 검색 url
17 - var league='silver_2'; 20 +
18 - var region='KR';
19 // 21 //
20 var cheerio=require('cheerio');//cheerio모듈 사용 22 var cheerio=require('cheerio');//cheerio모듈 사용
21 var request=require('request');//request모듈 사용 23 var request=require('request');//request모듈 사용
...@@ -50,20 +52,28 @@ app.get('/build/create',function(req,res,next){ ...@@ -50,20 +52,28 @@ app.get('/build/create',function(req,res,next){
50 var primary_race;//주 종족 52 var primary_race;//주 종족
51 var win_rate;//시즌 전체 승률 53 var win_rate;//시즌 전체 승률
52 54
55 + var region;//서버
56 + var league;//리그
53 var myrace;//내 종족 57 var myrace;//내 종족
54 var enemyrace;//상대 종족 58 var enemyrace;//상대 종족
59 + var enemyname;//상대 이름
60 +
55 var recommend;//추천빌드(운영/타이밍/올인) 61 var recommend;//추천빌드(운영/타이밍/올인)
56 // 62 //
57 //var answer=req.getParameter("name"); 63 //var answer=req.getParameter("name");
58 -var answer=req.query.name; 64 +region=req.query.region;
59 -answer=answer.toString(); 65 +league=req.query.league;
60 -console.log("query"+answer); 66 +myrace=req.query.myRace;
67 +enemyrace=req.query.enemyRace;
68 +enemyname=req.query.enemyName;
69 +
70 +console.log("query"+enemyname);
61 71
62 72
63 // r.question("분석을 원하는 아이디를 입력하세요 : ",function(answer){//question메소드에서 callback함수 생성 73 // r.question("분석을 원하는 아이디를 입력하세요 : ",function(answer){//question메소드에서 callback함수 생성
64 //question은 에러 제어 만들면 안된다. 74 //question은 에러 제어 만들면 안된다.
65 console.log("r.question processing");//callback함수란 이벤트가 왔을 때 실행되는 함수이다. answer에 검색을 원하는 아이디가 담겨있다. 75 console.log("r.question processing");//callback함수란 이벤트가 왔을 때 실행되는 함수이다. answer에 검색을 원하는 아이디가 담겨있다.
66 - rtfw1=rtfw1+answer;//검색 url 구성 76 + rtfw1=rtfw1+enemyname;//검색 url 구성
67 console.log(rtfw1);//테스트용 : 검색 url 확인 77 console.log(rtfw1);//테스트용 : 검색 url 확인
68 // 78 //
69 request(rtfw1,(error,response,body)=>{//rtfw url 불러오기 request 1 79 request(rtfw1,(error,response,body)=>{//rtfw url 불러오기 request 1
...@@ -75,7 +85,7 @@ console.log("query"+answer); ...@@ -75,7 +85,7 @@ console.log("query"+answer);
75 username=$(this).find('.name').text().trim();//name클래스를 찾아 공백빼고 텍스트화 85 username=$(this).find('.name').text().trim();//name클래스를 찾아 공백빼고 텍스트화
76 userleague=$(this).find('.league').text().trim();//league클래스를 찾아 공백빼고 텍스트화 86 userleague=$(this).find('.league').text().trim();//league클래스를 찾아 공백빼고 텍스트화
77 userregion=$(this).find('.region').text().trim();//region클래스를 찾아 공백빼고 텍스트화 87 userregion=$(this).find('.region').text().trim();//region클래스를 찾아 공백빼고 텍스트화
78 - if((username===answer)&&(userregion===region)){//아직 리그 구현 안함-리그는 그림으로 비교 88 + if((username===enemyname)&&(userregion===region)){//아직 리그 구현 안함-리그는 그림으로 비교
79 console.log(`${username}`);//테스트용 : 유저네임 출력 89 console.log(`${username}`);//테스트용 : 유저네임 출력
80 console.log(`${userregion}`);//테스트용 : 유저리전 출력 90 console.log(`${userregion}`);//테스트용 : 유저리전 출력
81 var usernumber=$(this).toString().slice(29,43);//rtfw에서 사용하는 사용자번호를 문자열로 넉넉히 자름 91 var usernumber=$(this).toString().slice(29,43);//rtfw에서 사용하는 사용자번호를 문자열로 넉넉히 자름
...@@ -220,7 +230,21 @@ console.log("query"+answer); ...@@ -220,7 +230,21 @@ console.log("query"+answer);
220 console.log("상대의 주 종족은 '"+primary_race+"'입니다."); 230 console.log("상대의 주 종족은 '"+primary_race+"'입니다.");
221 console.log("상대의 이번 시즌 전체 승률은 '"+win_rate+"'입니다."); 231 console.log("상대의 이번 시즌 전체 승률은 '"+win_rate+"'입니다.");
222 // 232 //
223 -res.render('index',{length: momentum}); 233 +js_momentum="최근 10경기 분석 결과 현재 상대는 '"+momentum+"'입니다.";
234 +js_terran_proficiency="상대는 테란 '"+terran_proficiency+"'입니다.";
235 +js_zerg_proficiency="상대는 저그 '"+zerg_proficiency+"'입니다.";
236 +js_protoss_proficiency="상대는 프로토스 '"+protoss_proficiency+"'입니다.";
237 +js_primary_race="상대의 주 종족은 '"+primary_race+"'입니다.";
238 +js_win_rate="상대의 이번 시즌 전체 승률은 '"+win_rate+"'입니다.";
239 +
240 +
241 +res.render('index',{top: '분석 결과',
242 +ejs_momentum: js_momentum,
243 +ejs_terran_proficiency: js_terran_proficiency,
244 +ejs_zerg_proficiency: js_zerg_proficiency,
245 +ejs_protoss_proficiency: js_protoss_proficiency,
246 +ejs_primary_race: js_primary_race,
247 +ejs_win_rate: js_win_rate});
224 //build recommend command 248 //build recommend command
225 249
226 // 250 //
......
1 -3303221
...\ No newline at end of file ...\ No newline at end of file
1 -<!DOCTYPE html>
2 -<html lang="ko-kr">
3 -<head>
4 - <meta charset="utf-8">
5 - <link href="//netdna.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" media="screen">
6 - <link href="/static/core/style.css" rel="stylesheet" media="screen">
7 - <script async="" src="//www.google-analytics.com/analytics.js"></script>
8 - <script type="text/javascript" async="" src="//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js"></script>
9 - <title>StarCraft 2 Build Recommendation Project</title>
10 -<body>
11 -
12 -<h1><%= data%></h1>
13 -
14 -
15 -<p stype="fond-family:verdana;">StarCraft 2 Build Recommendation Project</p>
16 -<img src="logoIMG.jpg" alt="StarCraft2 LOGO image">
17 -<br>
18 -<br>
19 -
20 -<div class="col-md-3">
21 - <form id="searchform" action method="get">
22 - <div id="div_id_race" class="form-group">
23 - <label for="id_sort_by" class="control-label ">
24 - 종족
25 - </label>
26 - <div class="controls">
27 - <select class="select form-control" id="id_sort_by" name="sort_by">
28 - <option value="t">테란</option>
29 - <option value="r">저그</option>
30 - <option value="a">프로토스</option>
31 - </select>
32 -</div>
33 -<a class="btn btn-primary" href="/build/create/">빌드</a>
34 -<br>
35 -<br>
36 -<a href="https://starcraft2.com/ko-kr/game">Official Site</a>
37 -</body>
38 -</html>