Spaces:
Runtime error
Runtime error
/* | |
[ jQuery ] | |
์น์ฌ์ดํธ์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฝ๊ฒ ํ์ฉํ ์ ์๋๋ก ๋์์ฃผ๋ ์คํ์์ค ๊ธฐ๋ฐ์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ | |
[ ์ต๊ทผ Trends + ๋น์ทํ ์ข ๋ฅ ] | |
1. Lodash | |
2. Moment | |
3. jQuery | |
4. date-fns | |
5. RxJS | |
*/ | |
/* | |
".ready()"๋ DOM(Document Object Model)์ด ์์ ํ ๋ถ๋ฌ์์ง๋ฉด ์คํ๋๋ Event ์ด๋ค. | |
์ผ๋ฐ์ ์ผ๋ก ๋ธ๋ผ์ฐ์ ๊ฐ HTML์ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด์๋ | |
๋จผ์ ๋ฌธ์ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค๊ณ ๋ง๋ค์ด์ง ๋ฌธ์ ๊ตฌ์กฐ ์์ ๋์์ธ์ ์ ํ๋ ํ์์ ์ทจํ๋ค. | |
์ด ๊ณผ์ ์์ ๋์์ธ์ด ์ ํ์ง์ง ์์ ์ํ๋ก ๋ฌธ์ ๊ตฌ์กฐ๊ฐ ๋ง๋ค์ด์ง ์์ ์ ์ํ๋๋ Event๊ฐ ".ready()" ์ด๋ค. | |
jQuery 3.0 ๋ฒ์ ์ดํ๋ถํฐ๋ "$(handler)" ๊ตฌ๋ฌธ๋ง ๊ถ์ฅ | |
".read()" Event๋ 1.8 ๋ฒ์ ์์๋ deprecated ๋์์ผ๋ฉฐ 3.0์์๋ ์ง์ํ์ง ์๊ธฐ ๋๋ฌธ | |
( ๊ทผ๋ฐ ์ฌ๊ธฐ์๋ ์คํ ๋ฌธ์ ์๋จ ) | |
*/ | |
// $(document).ready(function() { }); | |
$(function() { | |
var nasdaq_table_container_element = document.getElementById("nasdaq-table-container"); | |
var chart_container_element = document.getElementById("chart-container"); | |
var news_container_element = document.getElementById("news-container"); | |
console.log(nasdaq_table_container_element, chart_container_element, news_container_element); | |
// nasdaq_table_container_element.style.display = "block"; | |
// chart_container_element.style.display = "none"; | |
// news_container_element.style.display = "none"; | |
// $("#news-container").hide(); | |
// $("#news-container").show(); | |
nasdaq_table_init(); | |
}); | |
/** | |
* | |
* | |
* | |
* | |
*/ | |
function nasdaq_table_init() { | |
// HTML ์์ | |
$("#chart-container").hide(); | |
$("#news-container").hide(); | |
// Javascript -> Flask (Python) -> Javascript | |
output = sendAjax_sync("/stocks", {}, "json", handle_one_return); | |
// console.log("stocksInit() Output : ", output); | |
// console.log(typeof output); | |
// Ticker ๊ธธ์ด ํ์ธํด๋ณด๊ธฐ | |
var object_length = Object.keys(output.ticker).length; | |
// console.log(object_length); | |
// ๋๋๋ง HTML ์์ ์์ฑ | |
stocks = document.querySelector('.stocks'); | |
stocks.innerHTML = ''; | |
// "HTML"์ ์์ ์ถ๊ฐ | |
for (var i = 0; i < object_length; i++) { | |
stocks.innerHTML = stocks.innerHTML + '<div class="stock ticker"></div>'; | |
stocks.innerHTML = stocks.innerHTML + '<div class="stock name">' + output.name[i] + '</div>'; | |
if (output.diff[i] > 0) { | |
stocks.innerHTML = stocks.innerHTML + '<div class="stock diff up">' + '+' + output.diff[i] + ' %' + '</div>'; | |
} | |
else { stocks.innerHTML = stocks.innerHTML + '<div class="stock diff down">' + output.diff[i] + ' %' + '</div>'; } | |
stocks.innerHTML = stocks.innerHTML + '<div class="stock open">' + output.open[i] + '</div>'; | |
stocks.innerHTML = stocks.innerHTML + '<div class="stock close">' + output.close[i] + '</div>'; | |
stocks.innerHTML = stocks.innerHTML + '<div class="stock sector">' + output.sector[i] + '</div>'; | |
stocks.innerHTML = stocks.innerHTML + '<div class="stock industry">' + output.industry[i] + '</div>'; | |
// Add ticker's chart link | |
execution_function = `javascript:chartInit('${ output.ticker[i] }')`; | |
stock = document.querySelectorAll('.stock.ticker')[i]; | |
stock.innerHTML = ''; | |
stock.innerHTML = stock.innerHTML + `<a href=${ execution_function }>${ output.ticker[i] }</a>`; | |
} | |
} | |
/** | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
*/ | |
function chartInit(ticker, already=false) { | |
// HTML ์์ | |
$("#nasdaq-table-container").hide(); | |
$("#chart-container").show(); | |
$("#news-container").hide(); | |
// ticker ์ด๋ฆ ์ค์ (๋ถ์ ๋ชฉ ์ค์ ) | |
$('#chart-container .goticker .tickerName').text(ticker.concat(' Chart')); | |
// Javascript -> Flask (Python) -> Javascript | |
let [chart_data, news_articles] = sendAjax_sync_about_chartData_and_newsArticles("/chart", {"ticker": ticker}, "json", handle_two_return); | |
if (!already) { | |
// x์ถ๊ณผ data ์ค์ | |
// data: [{'x': date, 'o': open, 'h': high, 'l': low, 'c': close}, { }, { }, ... ] | |
data = []; | |
key_list = Object.keys(chart_data.Close); | |
for (var i=key_list.length-15; i<key_list.length; i++) { | |
key = key_list[i]; | |
const [year, month, day] = key.split("-"); | |
const x = new Date(parseInt(year), parseInt(month), parseInt(day), 9, 0, 0, 0).getTime(); | |
data.push({'x': x, 'o': chart_data.Open[key].toFixed(2), 'h': chart_data.High[key].toFixed(2), 'l': chart_data.Low[key].toFixed(2), 'c': chart_data.Close[key].toFixed(2)}) | |
} | |
// Javascript chart.js candlestick | |
let mychart = document.getElementById('myChart'); | |
new Chart(mychart, { | |
type: 'candlestick', | |
data: { | |
datasets: [{ | |
label: 'CHRT - '.concat(ticker), | |
data: data | |
}] | |
} | |
}); | |
} | |
////////////////////////////////////////////////////////////////// | |
// Javascript๋ฅผ ์ด์ฉํด HTML์ ๋์ ์ผ๋ก ํ๊ทธ ์ถ๊ฐ | |
// a ํ๊ทธ onclick ์ ์ฉ | |
var execution_function = `javascript:chartInit('${ticker}', true)`; | |
const goTicker = document.querySelector('#chart-container .goticker'); | |
goTicker.setAttribute('href', execution_function); | |
////////////////////////////////////////////////////////////////// | |
////////////////////////////////////////////////////////////////// | |
// table title ํ์ | |
// ํด๋น class์ text ์ง์ด๋ฃ๊ธฐ | |
const table_title = document.querySelector('.table-title'); | |
$('.table .table-title').text(ticker.concat(' News')); | |
news_table = document.querySelector('.table .news-table'); | |
// console.log(news_table.innerHTML); | |
// console.log(news); | |
// console.log(Object.keys(news)); // key ๋ฐฐ์ด ๋ง๋ค๊ธฐ | |
// console.log(typeof Object.keys(news)); | |
/* | |
[ ๋ ์ง ์ ๋ ฌ ] | |
"news"์์ index์ ๋ํด์ ์ ๋ ฌ์ ํ๊ณ reduce() ํจ์๋ฅผ ์ ์ฉ. | |
reduce() : ๋ฐฐ์ด์ ๊ฐ ์์์ ๋ํด ์ฃผ์ด์ง reducer ํจ์๋ฅผ ์คํํ๊ณ , ํ๋์ ๊ฒฐ๊ณผ๊ฐ์ ๋ฐํ | |
*/ | |
sorted_news = {} | |
sorted_news = Object.keys(news_articles).sort(function (a, b) { | |
if (a < b) { return 1; } | |
else if (a > b) { return -1; } | |
else { return 0; } | |
}).reduce((sorted_news, key) => { | |
sorted_news[key] = news_articles[key]; | |
return sorted_news; | |
}, {}); | |
// console.log(sorted_news); | |
var key_list = Object.keys(chart_data.Open); | |
var open_list = Object.values(chart_data.Open); | |
var close_list = Object.values(chart_data.Close); | |
for (var i=0; i<key_list.length; i++) { | |
const [year, month, day] = key_list[i].split("-"); | |
key_list[i] = year + '.' + month + '.' + day; | |
} | |
// console.log(key_list); | |
var link_list_idx = 0; | |
// List ์์ value๋ฅผ ๋ฝ์ ๋, (Python) => for item in list: | |
Object.keys(sorted_news).forEach(key => { | |
var date_idx_in_key_list = key_list.indexOf(String(key)); | |
// console.log(key, key_list, date_idx_in_key_list); | |
if (date_idx_in_key_list != -1) { | |
var diff = ((open_list[date_idx_in_key_list]-close_list[date_idx_in_key_list-1])/(open_list[date_idx_in_key_list]) * 100.0).toFixed(2); | |
} | |
else { var diff = 0; } | |
if (diff == 0) { | |
var diff_html = '<th class="news diff">0.0 %</th>'; | |
} | |
else if (diff > 0) { | |
var diff_html = '<th class="news diff up">+' + diff + ' %</th>'; | |
} | |
else { | |
var diff_html = '<th class="news diff down">' + diff + ' %</th>'; | |
} | |
var html = `<tr align="center" bgcolor="white"><th>+</th><th>${ key }</th>${ diff_html }<td style="text-align: left;">`; | |
for (var i = 0; i < sorted_news[key].length; i++) { | |
var title = sorted_news[key][i].substring(0, sorted_news[key][i].length-4); | |
var sendTitle = title; // Javascript -> Python ๋ณด๋ด๊ธฐ ์ํ title | |
// title์์ & ํ์๊ฐ ์์ ์ ์์. | |
// Title ์์ '&'๋ก ํ์๋์ด ์๋๋ฐ ๋ฐ๋ก ๊ตฌ๋ณํด์ผ ๋๋ค. | |
// andSymbolInTitle ์์ ๊ฐ์ ธ์จ '&' ์์น index๋ฅผ title๊ณผ ํฉ์ณ์ค๋ค. | |
andSymbolInTitle = []; | |
let idx = 0; | |
// title = "asdf&asdf&AS&DF&&"; | |
// sendTitle = title; | |
while (true) { | |
idx = sendTitle.indexOf('&', idx); | |
if (idx == -1) { break; } | |
sendTitle = sendTitle.substring(0, idx) + sendTitle.substring(idx+1, sendTitle.length); | |
// console.log(sendTitle); | |
andSymbolInTitle.push(idx + andSymbolInTitle.length); | |
} | |
var link = String(`/info_and_newsNER?ticker=${ ticker }&date=${ key }&title=${ sendTitle }&andSymbolInTitle=${ andSymbolInTitle }`); | |
linkList.push(link); | |
var execution_function = String(`javascript:getData(linkList[${ link_list_idx }], ${ diff });`); | |
html = html + `<a href="${ execution_function }">${ title }</a><br>`; | |
link_list_idx = link_list_idx + 1; | |
} | |
html = html + '</td>'; | |
news_table.innerHTML = news_table.innerHTML + html; | |
}); | |
} | |
linkList = []; | |
async function getData(link, diff) { | |
try { | |
console.log("link : ", link); | |
await $.getJSON(link, function(data) | |
{ | |
// console.log("ticker : ", data.ticker); | |
// console.log("date : ", data.date); | |
// console.log("title : ", data.title); | |
// console.log("url : ", data.url); | |
// console.log("ents : ", data.ents); | |
console.log("diff : ", diff); | |
newsInit(data.ticker, data.date, data.title, data.url, data.ents, diff); | |
}); | |
} catch (error) { | |
console.log("Error : ", error); | |
} | |
} | |
/** | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
*/ | |
function newsInit(ticker, date, title, url, ents, diff) { | |
// HTML ์์ | |
$("#nasdaq-table-container").hide(); | |
$("#chart-container").hide(); | |
$("#news-container").show(); | |
// console.log(ticker); | |
// console.log(date); | |
// console.log(title); | |
////////////////////////////////////////////////////////////////////// | |
// Javascript๋ฅผ ์ด์ฉํด HTML์ ๋์ ์ผ๋ก ํ๊ทธ ์ถ๊ฐ | |
document.querySelector('#news-container .goticker .tickerName').textContent = ticker + " Chart"; | |
document.querySelector('#news-container .titleDate').textContent = "Date : " + date; | |
document.querySelector('#news-container .titleName').textContent = "Article : " + title; | |
document.querySelector('#news-container .newsURL .input-News-URL').textContent = "URL : " + url; | |
// a ํ๊ทธ onclick ์ ์ฉ | |
var execution_function = `javascript:chartInit('${ ticker }', true)`; | |
const goTicker = document.querySelector('#news-container .goticker'); | |
goTicker.setAttribute('href', execution_function); | |
// a ํ๊ทธ์ URL ์ ์ฉ | |
const addURL = document.querySelector('.newsURL .input-News-URL'); | |
addURL.setAttribute('href', url); | |
// ๋ชจ๋ธ์์ ์ง๋ฌธ ์์ Ticker์ ์๋ง๊ฒ ์์ฑํ๊ธฐ | |
const model_input_example = document.querySelector('#model .text-form #text-input'); | |
if (diff == 0) { example = "What is your outlook for the future direction of this stock?" } | |
else if (diff > 0) { example = "Why did " + ticker + "'s stock go up?"; } | |
else if (diff < 0) { example = "Why did " + ticker + "'s stock go down?"; } | |
else { throw new Error('Error : diff Error '); } | |
model_input_example.setAttribute('value', example); | |
////////////////////////////////////////////////////////////////////// | |
// NER ๊ด๋ จ | |
console.log(ents); | |
let news = ents['news']; | |
let numOfNER = ents['text'].length; | |
// console.log("total news : ", news); | |
// ๋๋๋ง html ์์ ์์ฑ | |
news_ner = document.querySelector('.entities'); | |
news_ner.innerHTML = ''; | |
for (i=0; i<numOfNER; i++) { | |
start_idx = (i == 0) ? 0 : ents['end_char'][i-1]; | |
end_idx = ents['start_char'][i]; | |
last_idx = ents['end_char'][i]; | |
label = ents['label_'][i]; | |
if (label == 'ORG') { class_name = "entity_org"; } | |
else if (label == 'PERSON') { class_name = "entity_person"; } | |
else if (label == 'FAC') { class_name = "entity_fac"; } | |
else if (label == 'GPE') { class_name = "entity_gpe"; } | |
else if (label == 'PRODUCT') { class_name = "entity_product"; } | |
else { console.log("[ Error !!! - New NER label_ ] : ", ents['label_'][i], ents['text'][i]); class_name = "none"; } | |
add_html = news.substring(start_idx, end_idx); | |
add_html = add_html + '<mark class=' + class_name | |
+ ' style="line-height: 1;">' | |
+ news.substring(end_idx, last_idx) | |
+ '<span class="show-label" style="font-size: 0.8em; font-weight: bold; line-height: 1; border-radius: 0.35em; vertical-align: middle; margin-left: 0.5rem">' | |
+ label + '</span></mark>'; | |
// console.log(add_html); | |
news_ner.innerHTML = news_ner.innerHTML + add_html; | |
} | |
// console.log("last html : ", news.substring(ents['end_char'][numOfNER-1])); | |
news_ner.innerHTML = news_ner.innerHTML + news.substring(ents['end_char'][numOfNER-1]); | |
////////////////////////////////////////////////////////////////////// | |
// ๋ชจ๋ธ ์ ์ฉ ๋ด์ฉ ( Submit ) | |
var sendTitle = title; // Javascript -> Python ๋ณด๋ด๊ธฐ ์ํ title | |
// title์์ & ํ์๊ฐ ์์ ์ ์์. | |
// Title ์์ '&'๋ก ํ์๋์ด ์๋๋ฐ ๋ฐ๋ก ๊ตฌ๋ณํด์ผ ๋๋ค. | |
// andSymbolInTitle ์์ ๊ฐ์ ธ์จ '&' ์์น index๋ฅผ title๊ณผ ํฉ์ณ์ค๋ค. | |
andSymbolInTitle = []; | |
let idx = 0; | |
// title = "asdf&asdf&AS&DF&&"; | |
// sendTitle = title; | |
while (true) { | |
idx = sendTitle.indexOf('&', idx); | |
if (idx == -1) { break; } | |
sendTitle = sendTitle.substring(0, idx) + sendTitle.substring(idx+1, sendTitle.length); | |
// console.log(sendTitle); | |
andSymbolInTitle.push(idx + andSymbolInTitle.length); | |
} | |
// console.log(andSymbolInTitle); | |
// console.log("Last String", sendTitle); | |
// function ์์ "async"๋ฅผ ๋ถ์ด๋ฉด ํด๋น ํจ์๋ ํญ์ ํ๋ผ๋ฏธ์ค๋ฅผ ๋ฐํํ๋ค. | |
const translateText = async (text) => { | |
// ๋ชฉ์ : Flask์ input์ ๋ณด๋ด์ฃผ๊ณ output์ ๋ฐ์์ค๋ ๊ณผ์ | |
console.log("Start translateText async"); | |
// "await"๋ "async" ํจ์ ์์์๋ง ๋์ํ๋ค. | |
// "await" ํค์๋๋ฅผ ๋ง๋๋ฉด Promise๊ฐ ์ฒ๋ฆฌ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ๋ค. | |
// Promise๊ฐ ์ฒ๋ฆฌ๋๊ธธ ๊ธฐ๋ค๋ฆฌ๋ ๋์์ ์์ง์ด ๋ค๋ฅธ์ผ(๋ค๋ฅธ ์คํฌ๋ฆฝํธ๋ฅผ ์คํ, ์ด๋ฒคํธ ์ฒ๋ฆฌ ๋ฑ)์ ํ ์ ์๊ธฐ ๋๋ฌธ์, CPU ๋ฆฌ์์ค๊ฐ ๋ญ๋น๋์ง ์๋๋ค. | |
const inferResponse = await fetch(`newsQuestions?ticker=${ ticker }&date=${ date }&title=${ sendTitle }&andSymbolInTitle=${ andSymbolInTitle }&questions=${ text }`); // Javascript -> Flask(python) | |
// console.log("inferResponse : ", inferResponse); | |
const inferJson = await inferResponse.json(); // Flask(python) -> Javascript | |
// console.log(inferJson); | |
return inferJson.result['answer']; | |
}; | |
/* ๋ชจ๋ธ Submit button ๊ด๋ จ ๋ด์ฉ */ | |
// form ํ๊ทธ์ class ์ด๋ฆ | |
const textForm = document.querySelector('.text-form'); | |
// addEventListener(type, listener) | |
// addEventListener(type, listener, options) | |
// addEventListener(type, listener, useCapture) | |
textForm.addEventListener('submit', async (event) => { | |
event.preventDefault(); | |
// console.log(event); | |
// html -> javascript : input ๋ฐ์์์ output ๋ณด๋ด๊ธฐ | |
const textInput = document.getElementById('text-input'); | |
const textParagraph = document.querySelector('.text-output'); | |
console.log("textInput : ", textInput, textInput.value); | |
try { | |
// sendAjax("/inference", {"input_text" : textInput.value}, handleOutput); | |
// "await"๋ "async" ํจ์ ์์์๋ง ๋์ํ๋ค. | |
// "await" ํค์๋๋ฅผ ๋ง๋๋ฉด Promise๊ฐ ์ฒ๋ฆฌ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ๋ค. | |
// Promise๊ฐ ์ฒ๋ฆฌ๋๊ธธ ๊ธฐ๋ค๋ฆฌ๋ ๋์์ ์์ง์ด ๋ค๋ฅธ์ผ(๋ค๋ฅธ ์คํฌ๋ฆฝํธ๋ฅผ ์คํ, ์ด๋ฒคํธ ์ฒ๋ฆฌ ๋ฑ)์ ํ ์ ์๊ธฐ ๋๋ฌธ์, CPU ๋ฆฌ์์ค๊ฐ ๋ญ๋น๋์ง ์๋๋ค. | |
const answer = await translateText(textInput.value); // Flask์ input์ ๋ณด๋ด์ฃผ๊ณ output์ ๋ฐ์์ค๋ ๊ณผ์ | |
console.log("Result : ", answer); | |
textParagraph.textContent = answer; | |
} catch (err) { | |
console.error(err); | |
} | |
}); | |
} | |