From 1cd30f8e690ccc9b0de8bc2303f22789aa221b92 Mon Sep 17 00:00:00 2001 From: Bojun6667 <99935026+Bojun6667@users.noreply.github.com> Date: Thu, 5 Jan 2023 10:37:16 +0800 Subject: [PATCH 1/3] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2695c2b..50350e3 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,10 @@ 欄位 | 內容 -----|-------- 學期 | 111 學年上學期 -學生 | xxx -學號末兩碼 | xx +學生 | 黃柏鈞 +學號末兩碼 | 20 教師 | [陳鍾誠](https://www.nqu.edu.tw/educsie/index.php?act=blog&code=list&ids=4) 學校科系 | [金門大學資訊工程系](https://www.nqu.edu.tw/educsie/index.php) 課程教材 | https://gitlab.com/cccnqu111/ws +#本網頁是複製老師的專案並修改 From d008ba66ec4ddbfda13394aa2c80d9bc5a7b1d7f Mon Sep 17 00:00:00 2001 From: Bojun6667 <99935026+Bojun6667@users.noreply.github.com> Date: Thu, 5 Jan 2023 11:15:21 +0800 Subject: [PATCH 2/3] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 50350e3..ea25fc1 100644 --- a/README.md +++ b/README.md @@ -9,4 +9,4 @@ 學校科系 | [金門大學資訊工程系](https://www.nqu.edu.tw/educsie/index.php) 課程教材 | https://gitlab.com/cccnqu111/ws -#本網頁是複製老師的專案並修改 +# 本網頁是複製老師的專案並修改 From 938e61be8e86a78b20179e40c1069133679b1ed3 Mon Sep 17 00:00:00 2001 From: Bojun6667 <99935026+Bojun6667@users.noreply.github.com> Date: Thu, 5 Jan 2023 11:16:18 +0800 Subject: [PATCH 3/3] Add files via upload --- ws111a/README.md | 11 + ws111a/app.js | 60 ++++++ ws111a/db.js | 142 +++++++++++++ ws111a/hello1.js | 1 + ws111a/public/Myweb.css | 109 ++++++++++ ws111a/public/Myweb.js | 446 +++++++++++++++++++++++++++++++++++++++ ws111a/public/index.html | 23 ++ ws111a/server.js | 77 +++++++ ws111a/web.db | Bin 0 -> 20480 bytes 9 files changed, 869 insertions(+) create mode 100644 ws111a/README.md create mode 100644 ws111a/app.js create mode 100644 ws111a/db.js create mode 100644 ws111a/hello1.js create mode 100644 ws111a/public/Myweb.css create mode 100644 ws111a/public/Myweb.js create mode 100644 ws111a/public/index.html create mode 100644 ws111a/server.js create mode 100644 ws111a/web.db diff --git a/ws111a/README.md b/ws111a/README.md new file mode 100644 index 0000000..b5443f1 --- /dev/null +++ b/ws111a/README.md @@ -0,0 +1,11 @@ +# 課程:網站設計進階 -- 筆記、習題與報告 + +欄位 | 內容 +-----|-------- +學期 | 111 學年上學期 +學生 | xxx +學號末兩碼 | xx +教師 | [陳鍾誠](https://www.nqu.edu.tw/educsie/index.php?act=blog&code=list&ids=4) +學校科系 | [金門大學資訊工程系](https://www.nqu.edu.tw/educsie/index.php) +課程教材 | https://gitlab.com/cccnqu111/ws + diff --git a/ws111a/app.js b/ws111a/app.js new file mode 100644 index 0000000..b1e411b --- /dev/null +++ b/ws111a/app.js @@ -0,0 +1,60 @@ +import * as db from './db.js' +import {Server, sendJson, bodyParams, sendStatus, Status} from './server.js' + +db.open() + +const server = new Server() +server.public("/public") + +server.router.get('/', home) +.post('/login', login) +.post('/signup', signup) +.post('/rank', rank) + + +async function home(ctx) { + ctx.response.redirect("/public/#home") +} + +async function signup(ctx) { + const params = await bodyParams(ctx) + console.log('params=', params) + let user = await db.userGet(params.user) + if (user == null) { // user name available + console.log('signup:params=', params) + await db.userAdd({user:params.user, pass:params.password, email:params.email}) + sendStatus(ctx, Status.OK) + } + else + sendStatus(ctx, Status.Fail) +} + +async function login(ctx) { + const params = await bodyParams(ctx) + let user = await db.userGet(params.user) + console.log('login:user=', user) + if (user != null && user.pass == params.password) { + await ctx.state.session.set('user', user) + sendStatus(ctx, Status.OK) + } else + sendStatus(ctx, Status.Fail) +} + +async function rank(ctx){ + let user = await ctx.state.session.get('user') + console.log('user=',user.user) + const params = await bodyParams(ctx) + let user1 = params.user + console.log('user1=',user1) + let click = params.c + console.log('click=',click) + let player = {user:user, click:click} + if(user.user == user1){ + console.log("error") + await db.rankAdd(player) + sendStatus(ctx, Status.OK) + } + else{sendStatus(ctx, Status.Fail)} +} + +await server.listen(8000) diff --git a/ws111a/db.js b/ws111a/db.js new file mode 100644 index 0000000..1793ddc --- /dev/null +++ b/ws111a/db.js @@ -0,0 +1,142 @@ +import { DB } from "https://deno.land/x/sqlite/mod.ts"; + +let db = null +const NLIMIT = 100 + +export async function open() { + db = new DB("web.db"); + db.query(`CREATE TABLE IF NOT EXISTS users + (uid INTEGER PRIMARY KEY AUTOINCREMENT, + user TEXT, pass TEXT, email TEXT)`) + // https://www.sqlitetutorial.net/sqlite-full-text-search/ + // db.query(`CREATE VIRTUAL TABLE posts USING FTS5(title, body)`) + db.query(`CREATE TABLE IF NOT EXISTS rank(user TEXT, click INTEGER NOT NULL)`) +} + +export async function clear() { + db.query(`DELETE FROM users`) +} + +export async function close() { + db.close() +} + +export async function rankAdd(user){ + db.query(`INSERT INTO rank (user, click) VALUES (?,?)`, + [user.user, user.click]) +} + +export async function userAdd(user) { + db.query(`INSERT INTO users (user, pass, email) VALUES (?,?,?)`, + [user.user, user.pass, user.email]) +} + +export async function userGet(user1) { + let q = db.query(`SELECT uid, user, pass, email FROM users + WHERE user=?`, [user1]) + console.log(`userGet(${user1})=${q}`) + if (q.length <=0) return null + let [uid, user, pass, email] = q[0] + return {uid, user, pass, email} +} + +export async function userList() { + let q = db.query(`SELECT user FROM users`, []) + let users = [] + for (let [user] of q) { + users.push(user) + } + return users +} + +export async function replyAdd(reply) { + let time = reply.time || Date.now() + db.query('INSERT INTO replys (mid, msg, user, time) VALUES (?,?,?,?)', + [reply.mid, reply.msg, reply.user, time]) +} + +export async function msgAdd(msg) { + let time=msg.time || Date.now() + let r = db.query(`INSERT INTO msgs (msg, ufrom, uto, time) VALUES (?,?,?,?)`, + [msg.msg, msg.ufrom, msg.uto, time]) + r = db.query('SELECT last_insert_rowid()') + let mid = r[0][0] + let replys = msg.replys || [] + for (let reply of replys) { + reply.mid = mid + replyAdd(reply) + // r = db.query('INSERT INTO replys (mid, msg, user, time) VALUES (?,?,?,?)', + // [mid, reply.msg, reply.user, time]) + } + return mid +} + +export async function msgGet(mid) { + let q = db.query(`SELECT mid, msg, ufrom, uto, time + FROM msgs WHERE mid=?`, [mid]) + if (q.length <=0) return null + let [_mid, msg, ufrom, uto, time] = q[0] + q = db.query(`SELECT msg, user, time FROM replys WHERE mid=? ORDER BY time DESC`, [mid]) + let replys = [] + for (let [msg, user, time] of q) { + replys.push({msg, user, time}) + } + return {mid, msg, ufrom, uto, time, replys} +} + +export function queryToMsgs(q) { + let msgs = [] + for (let [mid, msg, ufrom, uto, time] of q) { + msgs.push({mid, msg, ufrom, uto, time}) + } + return msgs +} + +export async function msgTo(user) { + let q = db.query(`SELECT mid, msg, ufrom, uto, time + FROM msgs WHERE uto=? and uto!=ufrom + ORDER BY time DESC LIMIT ${NLIMIT}`, [user]) + return queryToMsgs(q) +} + +export async function msgBy(user) { + let q = db.query(`SELECT mid, msg, ufrom, uto, time + FROM msgs WHERE ufrom=? ORDER BY time DESC LIMIT ${NLIMIT}`, [user]) + return queryToMsgs(q) +} + +export async function msgFollow(follower) { + let q = db.query(`SELECT mid, msg, ufrom, uto, time FROM vFollowMsg + WHERE follower=? ORDER BY time DESC LIMIT ${NLIMIT}`, [follower]) + return queryToMsgs(q) +} + +export async function msgKey(key) { + let q = db.query(`SELECT mid, msg, ufrom, uto, time FROM msgs + WHERE LOWER(msg) LIKE '%${key.toLowerCase()}%' + ORDER BY time DESC LIMIT ${NLIMIT}`, []) + return queryToMsgs(q) +} + +export function followAdd(follower, user) { + db.query(`INSERT INTO follows (follower, user) VALUES (?,?)`, + [follower, user]) +} + +export async function followTo(user) { + let q = db.query(`SELECT user FROM follows WHERE follower=?`, [user]) + let follows = [] + for (let [follow] of q) { + follows.push(follow) + } + return follows +} + +export async function followBy(user) { + let q = db.query(`SELECT follower FROM follows WHERE user=?`, [user]) + let followers = [] + for (let [follower] of q) { + followers.push(follower) + } + return followers +} diff --git a/ws111a/hello1.js b/ws111a/hello1.js new file mode 100644 index 0000000..a909c6f --- /dev/null +++ b/ws111a/hello1.js @@ -0,0 +1 @@ +console.log('hello 你好!') diff --git a/ws111a/public/Myweb.css b/ws111a/public/Myweb.css new file mode 100644 index 0000000..740bf6f --- /dev/null +++ b/ws111a/public/Myweb.css @@ -0,0 +1,109 @@ +body{ + text-align: center; + background-color: rgb(246, 243, 239); +} + +ul{ + list-style-type: none; + margin: 0; + padding: 0; + overflow: hidden; + background-color: #333; +} + +ul a, .dropbtn { + display: inline-block; + color: white; + text-align: center; + padding: 14px 16px; + text-decoration: none; +} + +ul a:hover, .dropdown:hover .dropbtn { + background-color: red; +} + +ul.dropdown{ + display: inline-block; +} + +.dropdown-content { + display: none; + position: absolute; + background-color: #f9f9f9; + min-width: 160px; + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + z-index: 1; +} + +.dropdown-content a { + color: black; + padding: 12px 16px; + text-decoration: none; + display: block; + text-align: left; +} + +.dropdown-content a:hover {background-color: #f1f1f1;} + +.dropdown:hover .dropdown-content { + display: block; +} + +#container { + width: 400px; + height: 200px; + position: relative; + background: white; + margin: auto; +} +#animate { + width: 50px; + height: 50px; + position: absolute; + background-color: red; + margin: auto; +} +div.legends { + margin: 5px; + border: 1px solid #ccc; + width: 180px; + float: left; +} + +div.legends:hover { + border: 1px solid rgb(243, 9, 9); +} + +div.legends img { + width: 100%; + height: auto; +} + +div.legends desc{ + padding: 15px; + text-align: center; +} +div.seasons { + margin: 5px; + border: 1px solid #ccc; + display: block; + margin: auto; + width: 180px; +} + +div.seasons:hover { + border: 1px solid rgb(243, 9, 9); +} + +div.seasons img { + width: 100%; + height: auto; +} + +div.seasons desc{ + padding: 15px; + text-align: center; +} + +/* games */ diff --git a/ws111a/public/Myweb.js b/ws111a/public/Myweb.js new file mode 100644 index 0000000..e9ee798 --- /dev/null +++ b/ws111a/public/Myweb.js @@ -0,0 +1,446 @@ +window.onhashchange = async function () { + var tokens = window.location.hash.split('/') + var user + switch (tokens[0]) { + case '#home': + await home() + break + case '#signup': + await signup() + break + case '#login': + await login() + break + case '#userSays': + let user = uriDecode(tokens[1]) + await userSays(user) + break + case '#playgame': + await playgame() + break; + case '#legends': + await legends() + break; + case '#seasons': + await seasons() + break; + default: + console.log(`Error:hash=${tokens[0]}`) + // Ui.goto('#home') + break + } +} + +window.onload = function () { + window.onhashchange() +} + +async function home() { + Ui.show(`

個人資料

+ 大頭照 +

姓名:黃柏鈞

+

生日:92/04/30

+

興趣:玩遊戲、看影片、煮東西

+

Gmail:a0902301355@gmail.com

+

學歷:自強國小/自強國中/中和高中

+

目前就讀:國立金門大學資訊工程學系

`) +} + +async function signup() { + Ui.show(` +
+

註冊

+

+

+

+

+
`) +} + +async function login() { + Ui.show(` +
+

登入

+

+

+

+
`) +} + +async function serverSignup() { + let user = Ui.id('user').value + let password = Ui.id('password').value + let email = Ui.id('email').value + let r = await Server.post('/signup', {user, password, email}) + console.log('serverLogin: r=', r) + if (r.status == Status.OK) { + alert('註冊成功,開始登入使用!') + Ui.goto('#login') + } else { + alert('註冊失敗,請選擇另一個使用者名稱!') + } +} + +async function serverLogin() { + let user = Ui.id('user').value + let password = Ui.id('password').value + let r = await Server.post('/login', {user, password}) + console.log('serverLogin: r=', r) + if (r.status == Status.OK) { + localStorage.setItem('user', user) + alert('登入成功歡迎' + user) + Ui.goto(`#playgame/${user}`) + } else + alert('登入失敗: 請輸入正確的帳號密碼!') +} +var c = 0 +var number = 10 +var timeoutID = setInterval(1000) +async function playgame() { + Ui.show(` +
+
+

目前點擊次數:

+
10
+ + +
+ +
+
+ +
+ `) +} + +async function game() { + let r = document.getElementById("count") + c += 1 + r.innerHTML = `目前點擊次數:${c}` + + if(number == 0){ + document.getElementById("Button").disabled = true; + } +} + +async function start(){ + var timer = document.querySelector("#timer"); + timeoutID = setInterval(function(){ + number -- ; + if(number <= 0 ) + number = 0; + timer.innerText = number + 0 }, 1000); + if(number == 0){ + timeoutID = clearInterval(timeoutID) + } + return game +} + +async function reset(){ + number = 10 + timeoutID = clearInterval(timeoutID) + c = 0 +} + +async function rank(){ + let user = localStorage.getItem('user') + let r = await Server.post('/rank', {user, c}) + if (r.status == Status.OK){ + alert("已儲存紀錄") + } + else{alert("儲存失敗")} +} + +async function legends() { + Ui.show(`

Apex 人物整理

+

Apex Legends

+
+ + Bloodhound + +
Bloodhound
+
+ +
+ + Gibraltar + +
Gibraltar
+
+ +
+ + Lifeline + +
Lifeline
+
+ +
+ + Pathfinder + +
Pathfinder
+
+ +
+ + Wraith + +
Wraith
+
+ +
+ + Bangalore + +
Bangalore
+
+ +
+ + Caustic + +
Caustic
+
+ +
+ + Mirage + +
Mirage
+
+ +
+ + Octane + +
Octane
+
+ +
+ + Wattson + +
Wattson
+
+ +
+ + Crypto + +
Crypto
+
+ +
+ + Revenant + +
Revenant
+
+ +
+ + Loba + +
Loba
+
+ +
+ + Rampart + +
Rampart
+
+ +
+ + Horizon + +
Horizon
+
+ +
+ + Fuse + +
Fuse
+
+ +
+ + Valkyrie + +
Valkyrie
+
+
+ + Seer + +
Seer
+
+
+ + Ash + +
Ash
+
+
+ + Mad Maggie + +
Mad Maggie
+
+
+ + Newcastle + +
Newcastle
+
`) +} + +async function seasons(){ + Ui.show(`

Apex 各季影片整理

+

Apex Seasons

+
+ + Season1 + +
Season1
+
+
+ + Season2 + +
Season2
+
+
+ + Season3 + +
Season3
+
+
+ + Season4 + +
Season4
+
+
+ + Season5 + +
Season5
+
+
+ + Season6 + +
Season6
+
+
+ + Season7 + +
Season7
+
+
+ + Season8 + +
Season8
+
+
+ + Season9 + +
Season9
+
+
+ + Season10 + +
Season10
+
+
+ + Season11 + +
Season11
+
+
+ + Season12 + +
Season12
+
+
+ + Season13 + +
Season13
+
`) +} + +// ====================== Server ==================== +const Server = {} + +Server.get = async function(path) { + let r = await window.fetch(path, { + method: 'GET', + headers: { + 'Content-Type': 'application/json' + } + }) + return {status:r.status, obj:await r.json()} +} + +Server.post = async function(path, params) { + let r = await window.fetch(path, { + body: JSON.stringify(params), + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }) + return {status:r.status, obj:await r.json()} +} + +const Status = { + OK:200, + Fail:400, + Unauthorized:401, + Forbidden:403, + NotFound:404, +} + +// ========================= Ui ====================== +const Ui = {} + +Ui.id = function(path) { + return document.getElementById(path) +} + +Ui.one = function(path) { + return document.querySelector(path) +} + +Ui.showPanel = function(name) { + document.querySelectorAll('.panel').forEach((node)=>node.style.display='none') + Ui.id(name).style.display = 'block' +} + +Ui.show = function (html) { + Ui.id('main').innerHTML = html +} + +Ui.openNav = function () { + Ui.id('mySidenav').style.width = '200px' +} + +Ui.closeNav = function () { + Ui.id('mySidenav').style.width = '0' +} + +Ui.goto = function (hash) { + window.location.hash = hash +} diff --git a/ws111a/public/index.html b/ws111a/public/index.html new file mode 100644 index 0000000..145ffa8 --- /dev/null +++ b/ws111a/public/index.html @@ -0,0 +1,23 @@ + + + + + + +
+ + + \ No newline at end of file diff --git a/ws111a/server.js b/ws111a/server.js new file mode 100644 index 0000000..cf1af49 --- /dev/null +++ b/ws111a/server.js @@ -0,0 +1,77 @@ +import { Application, Router, send } from "https://deno.land/x/oak/mod.ts"; +import { Session } from "https://deno.land/x/oak_sessions/mod.ts"; + +export class Server { + constructor() { + this.app = new Application() + this.router = new Router() + } + public(path) { + this.router.get(`${path}/(.*)`, async (ctx)=>{ + console.log(ctx.request.url.pathname) + await send(ctx, ctx.request.url.pathname, { + root: `${Deno.cwd()}/`, + index: "index.html", + }) + }) + } + async listen(port) { + this.app.use(Session.initMiddleware()) + this.app.use(this.router.routes()) + this.app.use(this.router.allowedMethods()) + console.log(`Server run at http://127.0.0.1:${port}`) + await this.app.listen({ port }) + } +} + +export function sendJson(ctx, obj) { + ctx.response.type = 'application/json' + ctx.response.body = obj +} + +export const Status = { + OK:200, + Fail:400, + Unauthorized:401, + Forbidden:403, + NotFound:404, +} + +export function sendStatus(ctx, status) { + ctx.response.type = 'application/json' + ctx.response.status = status + ctx.response.body = {status} +} + +export async function bodyParams(ctx) { + let body = ctx.request.body() + if (body.type === "json") { + let params = await body.value + console.log('bodyParams:', params) + return params + } else { + console.log(`Error: body.type=${body.type}`) + } +} +/* +export async function formParams(ctx) { + let body = ctx.request.body() + if (body.type === "form") { + let params = await formParse(body) + console.log('params=',params) + return params + } + return null +} + +export async function formParse(body) { + const pairs = await body.value + const obj = {} + for (const [key, value] of pairs) { + obj[key] = value + } + return obj +} +*/ + + diff --git a/ws111a/web.db b/ws111a/web.db new file mode 100644 index 0000000000000000000000000000000000000000..c0568fa2d2f670173b88c972ff649ab4beddebc8 GIT binary patch literal 20480 zcmeI&&uZH+90zbIu4kOFxHJT_9yVbpO=xJh^aYX?Q^HcW^ITX?#>qV6#&-TVd4Tk| z$Js0N4fY=Gt@lc54NE#GV>@*4{Sn!ge*P))=O)nSPrY~^vTx&A8qC=t*(8*bHe-Yk zjW_k7QGVBX+u*GTG4@nwWZ&O@#otmYSHu_@uPaxTt*45RhX4d1009U<00Izz00bZa zfqx}Hcg%wWdiio543aRPCIf#SrW0Rw385NKE_Z&H^jm9h`>l;5*Y0>W^Ew}THnSe( zEmkk<)*=sQmhRbKye97rlXy6?^seLC$F|FyQ;#|4y$Va)_1LO4JweS5|PHx!seF+h-r`KI@!&r(K6naAG@N zbG?j-$(U4UlOWF@9>X+<6ZzbbdvoIlF>Z{X{Dy!41Rwwb2tWV=5P$##AOHafK;T&j zyirv0wz_*!#QWAE|Fxqajg$T1INdI(q*mL_!Z>-yBZ{JSB=-9vw@FoER;z>Y#Ui_} z6Z?N^+!Eu~xPBI&hebdD0uX=z1Rwwb2tWV=5P$##An?}$Rh=IR&`XL*|009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY>&vA`WZKEa{@ literal 0 HcmV?d00001