Commit c66d98af authored by nanahira's avatar nanahira

Merge branch 'v3-deck-category' into v3

parents d9b054c4 07f6530f
......@@ -43,7 +43,7 @@
</li>
</ul>
<span i18n *ngIf="grouped_apps.ygopro">YGOPro 各发行版</span>
<ul *ngIf="grouped_apps.recommend" class="nav nav-pills flex-column">
<ul *ngIf="grouped_apps.ygopro" class="nav nav-pills flex-column">
<li *ngFor="let app of grouped_apps.ygopro" class="nav-item">
<a (click)="$event.preventDefault(); chooseApp(app)" [href]="'https://mycard.moe/' + app.id" class="nav-link" [class.active]="app===currentApp">
<img *ngIf="app.icon" class="icon" [src]="app.icon">
......
......@@ -59,6 +59,7 @@
/*}*/
.small-gutters {
width: 35em;
margin-right: -5px;
margin-left: 0px;
}
......@@ -80,7 +81,9 @@
dl {
margin-bottom: 0;
}
#server-label{
height: 1.8125rem;
}
/*.modal-dialog {*/
/*max-width: 600px;*/
/*}*/
......@@ -297,4 +300,9 @@ form {
#title-filter-username {
margin-left: 6px;
}
\ No newline at end of file
}
.button-container {
display: flex;
justify-content: space-between;
}
<div *ngIf="!matching" id="action">
<button [disabled]="!appsService.allReady(app) || currentServer.id !== 'tiramisu'" (click)="request_match('athletic')" type="button" class="btn btn-primary btn-sm">
<i class="fa fa-play" aria-hidden="true"></i> <span i18n>竞技匹配</span></button>
<button i18n [disabled]="!appsService.allReady(app) || currentServer.id !== 'tiramisu'" (click)="request_match('entertain')" type="button" class="btn btn-secondary btn-sm">娱乐匹配</button>
<button i18n [disabled]="!appsService.allReady(app) || !currentServer.custom" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-list-modal">自定义游戏</button>
<button i18n [disabled]="!appsService.allReady(app) || !currentServer.windbot" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-create-windbot">单人模式</button>
<button i18n [disabled]="!appsService.allReady(app)" type="button" class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-replay-modal">观战录像</button>
</div>
<!-- 匹配中 -->
<div *ngIf="matching" id="match-time" class="input-group input-group-sm">
<div class="row small-gutters">
<!-- 环境选择器 -->
<div class="col-3 input-group input-group-sm">
<label i18n class="input-group-addon" id="server-label">环境</label>
<select class="form-control form-control-sm" id="selectServer" name="server"
[disabled]="!appsService.allReady(app)" [(ngModel)]="currentServer">
<option *ngFor="let server of selectableServers" [ngValue]="server">{{ server.name }}</option>
</select>
</div>
<!-- 匹配按钮 -->
<div class="col-9">
<div *ngIf="!matching" id="action" class="button-container">
<button [disabled]="!appsService.allReady(app) || currentServer.id !== 'tiramisu'"
(click)="request_match('athletic')" type="button" class="btn btn-primary btn-sm">
<i class="fa fa-play" aria-hidden="true"></i> <span i18n>竞技匹配</span></button>
<button i18n [disabled]="!appsService.allReady(app) || currentServer.id !== 'tiramisu'"
(click)="request_match('entertain')" type="button" class="btn btn-secondary btn-sm">娱乐匹配
</button>
<button i18n [disabled]="!appsService.allReady(app) || !currentServer.custom" type="button"
class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-list-modal">自定义游戏
</button>
<button i18n [disabled]="!appsService.allReady(app) || !currentServer.windbot" type="button"
class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#game-create-windbot">单人模式
</button>
<button i18n [disabled]="!appsService.allReady(app)" type="button" class="btn btn-secondary btn-sm"
data-toggle="modal" data-target="#game-replay-modal">观战录像
</button>
</div>
<!-- 匹配中-->
<div *ngIf="matching" id="match-time" class="button-container input-group input-group-sm ">
<span class="input-group-addon">
<i class="fa fa-futbol-o fa-spin" aria-hidden="true"></i>
<span i18n *ngIf="matching_arena == 'athletic'">竞技匹配</span>
<span i18n *ngIf="matching_arena == 'entertain'">娱乐匹配</span>
<span i18n *ngIf="matching_arena == 'athletic'" class="w-100">竞技匹配</span>
<span i18n *ngIf="matching_arena == 'entertain'" class="w-100">娱乐匹配</span>
</span>
<span class="input-group-addon"><span i18n>预计时间</span> 03:00</span><span class="input-group-addon"><span i18n>实际时间</span> {{match_time}}</span>
<span class="input-group-btn"><button i18n class="btn btn-secondary" type="button" [disabled]="!match_cancelable" (click)="cancel_match()">取消</button></span>
</div>
<span class="input-group-addon w-100">
<span i18n>预计时间</span> 03:00
</span>
<span class="input-group-addon w-100">
<span i18n>实际时间</span> {{ match_time }}
</span>
<span class="input-group-btn">
<button i18n class="btn btn-secondary" type="button" [disabled]="!match_cancelable"
(click)="cancel_match()">取消</button>
</span>
</div>
</div>
</div>
<div class="row small-gutters">
<div class="col-sm-4 input-group input-group-sm">
<label i18n class="input-group-addon" id="server-label">环境</label>
<select class="form-control form-control-sm" id="selectServer" name="server" [disabled]="!appsService.allReady(app)" [(ngModel)]="currentServer">
<option *ngFor="let server of selectableServers" [ngValue]="server">{{server.name}}</option>
<!-- <div class="col-sm-3 input-group input-group-sm">-->
<!-- <label i18n class="input-group-addon" id="server-label">环境</label>-->
<!-- <select class="form-control form-control-sm" id="selectServer" name="server"-->
<!-- [disabled]="!appsService.allReady(app)" [(ngModel)]="currentServer">-->
<!-- <option *ngFor="let server of selectableServers" [ngValue]="server">{{ server.name }}</option>-->
<!-- </select>-->
<!-- </div>-->
<div *ngIf="lastCategoryFormat" class="input-group input-group-sm col-6">
<label i18n class="input-group-addon" id="basic-addon1">分类</label>
<select class="form-control form-control-sm" id="exampleSelect1" name="category" [(ngModel)]="currentCategory"
(ngModelChange)="refreshCurrentCategoryDecks()">
<option *ngFor="let category of categories" [ngValue]="category">{{ category.title }}</option>
</select>
</div>
<div class="col-sm-8 input-group input-group-sm">
<div class="input-group input-group-sm " [class.col-sm-6]="!!lastCategoryFormat" [class.col-sm-12]="!lastCategoryFormat"
[class.col-sm-7]="!lastCategoryFormat">
<label i18n class="input-group-addon" id="basic-addon1">卡组</label>
<select class="form-control form-control-sm" id="exampleSelect1" name="deck" [(ngModel)]="current_deck">
<option *ngFor="let deck of decks" [ngValue]="deck">{{deck}}</option>
<select class="form-control form-control-sm" id="exampleSelect1" name="deck" [(ngModel)]="currentDeck">
<option *ngFor="let deck of currentCategoryDecks" [ngValue]="deck">{{ deck }}</option>
</select> <span class="input-group-btn">
<button id="edit_deck_button" i18n [disabled]="!appsService.allReady(app)" class="btn btn-secondary btn-sm" (click)="edit_deck(current_deck)">编辑</button>
<button id="edit_deck_button" i18n [disabled]="!appsService.allReady(app)" class="btn btn-secondary btn-sm"
(click)="edit_deck()">编辑</button>
</span>
</div>
</div>
<div class="modal fade" id="game-create-windbot" *ngIf="currentServer.windbot" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal fade" id="game-create-windbot" *ngIf="currentServer.windbot" tabindex="-1" role="dialog"
aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
......@@ -47,7 +90,8 @@
<label i18n>选择对手</label>
<div id="windbot" class="list-group">
<a i18n href="#" class="list-group-item" (click)="join_windbot()">随机</a>
<a *ngFor="let name of windbot" href="#" class="list-group-item" (click)="join_windbot(name)">{{name}}</a>
<a *ngFor="let name of windbot" href="#" class="list-group-item"
(click)="join_windbot(name)">{{ name }}</a>
</div>
</div>
<div class="modal-footer">
......@@ -57,13 +101,16 @@
</div>
</div>
<div class="modal fade" id="game-list-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal fade" id="game-list-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content flex-row">
<div id="game-list">
<div i18n class="p-2" *ngIf="rooms_loading">正在读取游戏列表...</div>
<div i18n class="p-2" *ngIf="!rooms_loading && this.rooms.length === 0">现在没有等待中的游戏,可以自行创建一个房间或者去匹配</div>
<div i18n class="p-2" *ngIf="!rooms_loading && this.rooms.length === 0">
现在没有等待中的游戏,可以自行创建一个房间或者去匹配
</div>
<table *ngIf="!this.rooms_loading && this.rooms.length > 0" class="table table-striped table-hover">
<thead>
<tr>
......@@ -76,9 +123,12 @@
<tbody>
<tr *ngFor="let room of rooms_show" class="room" (click)="join_room(room)">
<td class="title">{{room.title}}</td>
<td class="title">{{ room.title }}</td>
<td class="users">
<img *ngFor="let user of room.users" class="avatar rounded" [src]="'https://ygobbs.com/user_avatar/ygobbs.com/' + user.username + '/25/1.png'" data-toggle="tooltip" data-placement="bottom" [title]="user.username" (error)="avatar_fallback($event)">
<img *ngFor="let user of room.users" class="avatar rounded"
[src]="'https://ygobbs.com/user_avatar/ygobbs.com/' + user.username + '/25/1.png'"
data-toggle="tooltip" data-placement="bottom" [title]="user.username"
(error)="avatar_fallback($event)">
</td>
<td class="mode">
<span i18n *ngIf="room.options.mode === 0">单局模式</span>
......@@ -86,27 +136,49 @@
<span i18n *ngIf="room.options.mode === 2">TAG</span>
</td>
<td class="extra">
<span i18n i18n-title *ngIf="room.options.rule != default_options.rule && room.options.rule == 0" title="允许OCG独有卡,不允许TCG独有卡">OCG</span>
<span i18n i18n-title *ngIf="room.options.rule != default_options.rule && room.options.rule == 1" title="允许TCG独有卡,不允许OCG独有卡">TCG</span>
<span i18n i18n-title *ngIf="room.options.rule != default_options.rule && room.options.rule == 2" title="只允许简体中文版已经发售的卡">简中</span>
<span i18n i18n-title *ngIf="room.options.rule != default_options.rule && room.options.rule == 3" title="只允许自制卡">自制卡</span>
<span i18n i18n-title *ngIf="room.options.rule != default_options.rule && room.options.rule == 4" title="不允许OCG或TCG独有卡">专有卡禁止</span>
<span i18n i18n-title *ngIf="room.options.rule != default_options.rule && room.options.rule == 5" title="可以任意使用OCG或TCG卡">所有卡片</span>
<span i18n *ngIf="room.options.start_lp != default_options.start_lp">{{room.options.start_lp}}LP</span>
<span i18n i18n-title *ngIf="room.options.start_hand != default_options.start_hand" title="初始起手数量">{{room.options.start_hand}}初始</span>
<span i18n i18n-title *ngIf="room.options.draw_count != default_options.draw_count" title="每回合抽卡数量">{{room.options.draw_count}}抽卡</span>
<span i18n i18n-title *ngIf="room.options.duel_rule != default_options.duel_rule" title="上个版本的大师规则">大师规则{{room.options.duel_rule}}</span>
<span i18n i18n-title *ngIf="room.options.no_check_deck != default_options.no_check_deck" title="不检查卡组是否合规">不检查</span>
<span i18n i18n-title *ngIf="room.options.no_shuffle_deck != default_options.no_shuffle_deck" title="任何时候都不洗切卡组">不洗卡</span>
<span i18n i18n-title *ngIf="!!room.options.auto_death" title="40分钟自动死三">自动加时赛</span>
<span i18n i18n-title
*ngIf="room.options.rule != default_options.rule && room.options.rule == 0"
title="允许OCG独有卡,不允许TCG独有卡">OCG</span>
<span i18n i18n-title
*ngIf="room.options.rule != default_options.rule && room.options.rule == 1"
title="允许TCG独有卡,不允许OCG独有卡">TCG</span>
<span i18n i18n-title
*ngIf="room.options.rule != default_options.rule && room.options.rule == 2"
title="只允许简体中文版已经发售的卡">简中</span>
<span i18n i18n-title
*ngIf="room.options.rule != default_options.rule && room.options.rule == 3"
title="只允许自制卡">自制卡</span>
<span i18n i18n-title
*ngIf="room.options.rule != default_options.rule && room.options.rule == 4"
title="不允许OCG或TCG独有卡">专有卡禁止</span>
<span i18n i18n-title
*ngIf="room.options.rule != default_options.rule && room.options.rule == 5"
title="可以任意使用OCG或TCG卡">所有卡片</span>
<span i18n
*ngIf="room.options.start_lp != default_options.start_lp">{{ room.options.start_lp }}LP</span>
<span i18n i18n-title *ngIf="room.options.start_hand != default_options.start_hand"
title="初始起手数量">{{ room.options.start_hand }}初始</span>
<span i18n i18n-title *ngIf="room.options.draw_count != default_options.draw_count"
title="每回合抽卡数量">{{ room.options.draw_count }}抽卡</span>
<span i18n i18n-title *ngIf="room.options.duel_rule != default_options.duel_rule"
title="上个版本的大师规则">大师规则{{ room.options.duel_rule }}</span>
<span i18n i18n-title *ngIf="room.options.no_check_deck != default_options.no_check_deck"
title="不检查卡组是否合规">不检查</span>
<span i18n i18n-title
*ngIf="room.options.no_shuffle_deck != default_options.no_shuffle_deck"
title="任何时候都不洗切卡组">不洗卡</span>
<span i18n i18n-title *ngIf="!!room.options.auto_death"
title="40分钟自动死三">自动加时赛</span>
</td>
</tr>
</tbody>
</table>
<div id="join-private" class="input-group input-group-sm">
<i class="fa fa-key input-group-addon" aria-hidden="true"></i>
<input [(ngModel)]="join_password" type="text" class="form-control" i18n-placeholder placeholder="在这输入你朋友的私密房间密码就可以进去了哦!">
<span class="input-group-btn"><button i18n class="btn btn-secondary" type="button" (click)="join_private(join_password)">加入私密房间</button></span>
<input [(ngModel)]="join_password" type="text" class="form-control" i18n-placeholder
placeholder="在这输入你朋友的私密房间密码就可以进去了哦!">
<span class="input-group-btn"><button i18n class="btn btn-secondary" type="button"
(click)="join_private(join_password)">加入私密房间</button></span>
</div>
</div>
......@@ -116,16 +188,20 @@
<div class="form-group">
<ng-container *ngIf="!room.private; else private">
<label i18n for="game-create-title">游戏标题</label>
<input type="text" maxlength="12" class="form-control form-control-sm" id="game-create-title" name="title" [(ngModel)]="room.title" required [readonly]>
<input type="text" maxlength="12" class="form-control form-control-sm" id="game-create-title"
name="title" [(ngModel)]="room.title" required [readonly]>
<small i18n class="form-text text-muted">最多 12 个字</small>
</ng-container>
<ng-template #private>
<label *ngIf="room.private" for="game-create-title"><i class="fa fa-key" aria-hidden="true"></i>
<span i18n>房间密码</span></label>
<div class="input-group input-group-sm">
<input type="text" maxlength="12" class="form-control" id="game-create-title" name="title" [(ngModel)]="host_password" readonly>
<span i18n-title id="copy-wrapper" class="input-group-btn" data-toggle="tooltip" title="房间密码已复制到剪贴板">
<button i18n-title class="btn btn-secondary fa fa-clipboard" type="button" title="复制" (click)="copy(host_password, $event)"></button>
<input type="text" maxlength="12" class="form-control" id="game-create-title" name="title"
[(ngModel)]="host_password" readonly>
<span i18n-title id="copy-wrapper" class="input-group-btn" data-toggle="tooltip"
title="房间密码已复制到剪贴板">
<button i18n-title class="btn btn-secondary fa fa-clipboard" type="button" title="复制"
(click)="copy(host_password, $event)"></button>
</span>
</div>
<small i18n class="form-text text-muted">把这个分享给你的朋友</small>
......@@ -134,7 +210,8 @@
</div>
<div class="form-group">
<label i18n for="game-create-rule">卡片允许</label>
<select class="form-control form-control-sm" id="game-create-rule" name="rule" [(ngModel)]="room.options.rule">
<select class="form-control form-control-sm" id="game-create-rule" name="rule"
[(ngModel)]="room.options.rule">
<option i18n value="0">OCG</option>
<option i18n value="1">TCG</option>
<option i18n value="2">简体中文</option>
......@@ -145,7 +222,9 @@
</div>
<div class="form-group">
<label i18n for="game-create-mode">决斗模式</label>
<select class="form-control form-control-sm" id="game-create-mode" name="mode" (change)="room.options.start_lp = room.options.mode == 2 ? default_options.start_lp_tag : default_options.start_lp" [(ngModel)]="room.options.mode">
<select class="form-control form-control-sm" id="game-create-mode" name="mode"
(change)="room.options.start_lp = room.options.mode == 2 ? default_options.start_lp_tag : default_options.start_lp"
[(ngModel)]="room.options.mode">
<option i18n value="0">单局模式</option>
<option i18n value="1">比赛模式</option>
<option i18n value="2">TAG</option>
......@@ -153,7 +232,8 @@
</div>
<div class="form-group">
<label i18n for="game-create-duelrule">决斗规则</label>
<select class="form-control form-control-sm" id="game-create-duelrule" name="duel_rule" [(ngModel)]="room.options.duel_rule">
<select class="form-control form-control-sm" id="game-create-duelrule" name="duel_rule"
[(ngModel)]="room.options.duel_rule">
<option i18n value="1">大师规则1</option>
<option i18n value="2">大师规则2</option>
<option i18n value="3">大师规则3</option>
......@@ -167,19 +247,22 @@
<div class="row">
<label i18n for="game-create-start-lp" class="col-sm-6 col-form-label">初始 LP</label>
<div class="col-sm-6">
<input type="number" value="8000" min="1" max="65536" class="form-control form-control-sm" id="game-create-start-lp" name="start_lp" [(ngModel)]="room.options.start_lp">
<input type="number" value="8000" min="1" max="65536" class="form-control form-control-sm"
id="game-create-start-lp" name="start_lp" [(ngModel)]="room.options.start_lp">
</div>
</div>
<div class="row">
<label i18n for="game-create-start-hand" class="col-sm-6 col-form-label">初始手牌数</label>
<div class="col-sm-6">
<input type="number" value="5" min="0" max="16" class="form-control form-control-sm" id="game-create-start-hand" name="start_hand" [(ngModel)]="room.options.start_hand">
<input type="number" value="5" min="0" max="16" class="form-control form-control-sm"
id="game-create-start-hand" name="start_hand" [(ngModel)]="room.options.start_hand">
</div>
</div>
<div class="row">
<label i18n for="game-create-draw-count" class="col-sm-6 col-form-label">每回合抽卡</label>
<div class="col-sm-6">
<input type="number" value="1" min="0" max="16" class="form-control form-control-sm" id="game-create-draw-count" name="draw_count" [(ngModel)]="room.options.draw_count">
<input type="number" value="1" min="0" max="16" class="form-control form-control-sm"
id="game-create-draw-count" name="draw_count" [(ngModel)]="room.options.draw_count">
</div>
</div>
<div>
......@@ -191,11 +274,13 @@
<label i18n for="enable_priority">旧规则</label>
</div-->
<div>
<input id="no_check_deck" name="no_check_deck" [(ngModel)]="room.options.no_check_deck" type="checkbox">
<input id="no_check_deck" name="no_check_deck" [(ngModel)]="room.options.no_check_deck"
type="checkbox">
<label i18n for="no_check_deck">不检查卡组</label>
</div>
<div>
<input id="no_shuffle_deck" name="no_shuffle_deck" type="checkbox" [(ngModel)]="room.options.no_shuffle_deck">
<input id="no_shuffle_deck" name="no_shuffle_deck" type="checkbox"
[(ngModel)]="room.options.no_shuffle_deck">
<label i18n for="no_shuffle_deck">不洗切卡组</label>
</div>
<div>
......@@ -216,7 +301,8 @@
</div>
<div class="modal fade" id="game-replay-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal fade" id="game-replay-modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<!--<div class="modal-header">-->
......@@ -257,43 +343,56 @@
<th class="mode">
<!--<span i18n>游戏模式</span>-->
<div id="watch-filter" class="dropdown">
<button i18n class="btn btn-secondary dropdown-toggle btn-sm" type="button" id="watchDropdownMenuButton" aria-haspopup="true" aria-expanded="false">游戏模式</button>
<button i18n class="btn btn-secondary dropdown-toggle btn-sm" type="button"
id="watchDropdownMenuButton" aria-haspopup="true" aria-expanded="false">
游戏模式
</button>
<div class="dropdown-menu">
<h6 i18n class="dropdown-header">匹配</h6>
<label i18n class="form-check dropdown-item">
<input type="checkbox" class="form-check-input" [(ngModel)]="replay_rooms_filter.athletic">
<input type="checkbox" class="form-check-input"
[(ngModel)]="replay_rooms_filter.athletic">
竞技匹配
</label>
<label i18n class="form-check dropdown-item">
<input type="checkbox" class="form-check-input" [(ngModel)]="replay_rooms_filter.entertain">
<input type="checkbox" class="form-check-input"
[(ngModel)]="replay_rooms_filter.entertain">
娱乐匹配
</label>
<h6 i18n class="dropdown-header">自定义游戏</h6>
<label i18n class="form-check dropdown-item">
<input type="checkbox" class="form-check-input" [(ngModel)]="replay_rooms_filter.single">
<input type="checkbox" class="form-check-input"
[(ngModel)]="replay_rooms_filter.single">
单局模式
</label>
<label i18n class="form-check dropdown-item">
<input type="checkbox" class="form-check-input" [(ngModel)]="replay_rooms_filter.match">
<input type="checkbox" class="form-check-input"
[(ngModel)]="replay_rooms_filter.match">
比赛模式
</label>
<label i18n class="form-check dropdown-item">
<input type="checkbox" class="form-check-input" [(ngModel)]="replay_rooms_filter.tag">
<input type="checkbox" class="form-check-input"
[(ngModel)]="replay_rooms_filter.tag">
TAG
</label>
<h6 i18n class="dropdown-header">单人模式</h6>
<label i18n class="form-check dropdown-item">
<input type="checkbox" class="form-check-input" [(ngModel)]="replay_rooms_filter.windbot">
<input type="checkbox" class="form-check-input"
[(ngModel)]="replay_rooms_filter.windbot">
单人模式
</label>
</div>
</div>
</th>
<th class="title">
<div class="d-flex">
<span i18n class="align-self-end">游戏标题</span>
<input i18n-placeholder type="text" class="col-sm-6 form-control form-control-sm" id="title-filter-username" placeholder="支持玩家名称搜索房间" [(ngModel)]="replay_rooms_filter.username" (ngModelChange)="title_username_change_handler($event)" />
</div>
<div class="d-flex">
<span i18n class="align-self-end">游戏标题</span>
<input i18n-placeholder type="text"
class="col-sm-6 form-control form-control-sm" id="title-filter-username"
placeholder="支持玩家名称搜索房间"
[(ngModel)]="replay_rooms_filter.username"
(ngModelChange)="title_username_change_handler($event)"/>
</div>
</th>
<th i18n class="users">玩家</th>
<th i18n class="extra">额外选项</th>
......@@ -305,33 +404,65 @@
<span i18n *ngIf="room.id.startsWith('AI#')">单人模式</span>
<span i18n *ngIf="room.arena === 'athletic'">竞技匹配</span>
<span i18n *ngIf="room.arena === 'entertain'">娱乐匹配</span>
<span i18n *ngIf="!(room.arena || room.id.startsWith('AI#')) && room.options.mode === 0">单局模式</span>
<span i18n *ngIf="!(room.arena || room.id.startsWith('AI#')) && room.options.mode === 1">比赛模式</span>
<span i18n *ngIf="!(room.arena || room.id.startsWith('AI#')) && room.options.mode === 2">TAG</span>
<span i18n
*ngIf="!(room.arena || room.id.startsWith('AI#')) && room.options.mode === 0">单局模式</span>
<span i18n
*ngIf="!(room.arena || room.id.startsWith('AI#')) && room.options.mode === 1">比赛模式</span>
<span i18n
*ngIf="!(room.arena || room.id.startsWith('AI#')) && room.options.mode === 2">TAG</span>
</td>
<td class="title">
<span i18n *ngIf="room.private">{{room.users[0] && room.users[0].username}} 的私密房间</span>
<span i18n *ngIf="room.arena || room.id.startsWith('AI#')">{{room.users[0] && room.users[0].username}} 跟 {{room.users[1] && room.users[1].username}} 的决斗</span>
<span *ngIf="!(room.arena || room.id.startsWith('AI#') || room.private)">{{room.title}}</span>
<span i18n
*ngIf="room.private">{{ room.users[0] && room.users[0].username }} 的私密房间</span>
<span i18n
*ngIf="room.arena || room.id.startsWith('AI#')">{{ room.users[0] && room.users[0].username }} 跟 {{ room.users[1] && room.users[1].username }} 的决斗</span>
<span *ngIf="!(room.arena || room.id.startsWith('AI#') || room.private)">{{ room.title }}</span>
</td>
<td class="users">
<img *ngFor="let user of room.users" class="avatar rounded" [src]="'https://ygobbs.com/user_avatar/ygobbs.com/' + user.username + '/25/1.png'" data-toggle="tooltip" data-placement="bottom" [title]="user.username" (error)="avatar_fallback($event)">
<img *ngFor="let user of room.users" class="avatar rounded"
[src]="'https://ygobbs.com/user_avatar/ygobbs.com/' + user.username + '/25/1.png'"
data-toggle="tooltip" data-placement="bottom" [title]="user.username"
(error)="avatar_fallback($event)">
</td>
<td class="extra">
<div *ngIf="!(room.arena || room.id.startsWith('AI#'))">
<span i18n i18n-title *ngIf="room.options.rule != default_options.rule && room.options.rule == 0" title="允许OCG独有卡,不允许TCG独有卡">OCG</span>
<span i18n i18n-title *ngIf="room.options.rule != default_options.rule && room.options.rule == 1" title="允许TCG独有卡,不允许OCG独有卡">TCG</span>
<span i18n i18n-title *ngIf="room.options.rule != default_options.rule && room.options.rule == 2" title="只允许简体中文版已经发售的卡">简中</span>
<span i18n i18n-title *ngIf="room.options.rule != default_options.rule && room.options.rule == 3" title="只允许自制卡">自制卡</span>
<span i18n i18n-title *ngIf="room.options.rule != default_options.rule && room.options.rule == 4" title="不允许OCG或TCG独有卡">专有卡禁止</span>
<span i18n i18n-title *ngIf="room.options.rule != default_options.rule && room.options.rule == 5" title="可以任意使用OCG或TCG卡">所有卡片</span>
<span i18n *ngIf="room.options.start_lp != default_options.start_lp && room.options.mode != 2">{{room.options.start_lp}}LP</span>
<span i18n *ngIf="room.options.start_lp != default_options.start_lp_tag && room.options.mode == 2">{{room.options.start_lp}}LP</span>
<span i18n i18n-title *ngIf="room.options.start_hand != default_options.start_hand" title="初始起手数量">{{room.options.start_hand}}初始</span>
<span i18n i18n-title *ngIf="room.options.draw_count != default_options.draw_count" title="每回合抽卡数量">{{room.options.draw_count}}抽卡</span>
<span i18n i18n-title *ngIf="room.options.duel_rule != default_options.duel_rule" title="上个版本的大师规则">大师规则{{room.options.duel_rule}}</span>
<span i18n i18n-title *ngIf="room.options.no_check_deck != default_options.no_check_deck" title="不检查卡组是否合规">不检查</span>
<span i18n i18n-title *ngIf="room.options.no_shuffle_deck != default_options.no_shuffle_deck" title="任何时候都不洗切卡组">不洗卡</span>
<span i18n i18n-title
*ngIf="room.options.rule != default_options.rule && room.options.rule == 0"
title="允许OCG独有卡,不允许TCG独有卡">OCG</span>
<span i18n i18n-title
*ngIf="room.options.rule != default_options.rule && room.options.rule == 1"
title="允许TCG独有卡,不允许OCG独有卡">TCG</span>
<span i18n i18n-title
*ngIf="room.options.rule != default_options.rule && room.options.rule == 2"
title="只允许简体中文版已经发售的卡">简中</span>
<span i18n i18n-title
*ngIf="room.options.rule != default_options.rule && room.options.rule == 3"
title="只允许自制卡">自制卡</span>
<span i18n i18n-title
*ngIf="room.options.rule != default_options.rule && room.options.rule == 4"
title="不允许OCG或TCG独有卡">专有卡禁止</span>
<span i18n i18n-title
*ngIf="room.options.rule != default_options.rule && room.options.rule == 5"
title="可以任意使用OCG或TCG卡">所有卡片</span>
<span i18n
*ngIf="room.options.start_lp != default_options.start_lp && room.options.mode != 2">{{ room.options.start_lp }}LP</span>
<span i18n
*ngIf="room.options.start_lp != default_options.start_lp_tag && room.options.mode == 2">{{ room.options.start_lp }}LP</span>
<span i18n i18n-title
*ngIf="room.options.start_hand != default_options.start_hand"
title="初始起手数量">{{ room.options.start_hand }}初始</span>
<span i18n i18n-title
*ngIf="room.options.draw_count != default_options.draw_count"
title="每回合抽卡数量">{{ room.options.draw_count }}抽卡</span>
<span i18n i18n-title
*ngIf="room.options.duel_rule != default_options.duel_rule"
title="上个版本的大师规则">大师规则{{ room.options.duel_rule }}</span>
<span i18n i18n-title
*ngIf="room.options.no_check_deck != default_options.no_check_deck"
title="不检查卡组是否合规">不检查</span>
<span i18n i18n-title
*ngIf="room.options.no_shuffle_deck != default_options.no_shuffle_deck"
title="任何时候都不洗切卡组">不洗卡</span>
<span i18n i18n-title *ngIf="!!room.options.auto_death" title="40分钟自动死三">自动加时赛</span>
</div>
</td>
......@@ -341,8 +472,10 @@
</div>
<div class="tab-pane" id="game-replay-local" role="tabpanel">
<div class="list-group">
<a *ngFor="let replay of replays2" class="list-group-item list-group-item-action" (click)="watch_replay2(replay)">{{replay}}</a>
<a *ngFor="let replay of replays" class="list-group-item list-group-item-action" (click)="watch_replay(replay)">{{replay}}</a>
<a *ngFor="let replay of replays2" class="list-group-item list-group-item-action"
(click)="watch_replay2(replay)">{{ replay }}</a>
<a *ngFor="let replay of replays" class="list-group-item list-group-item-action"
(click)="watch_replay(replay)">{{ replay }}</a>
</div>
</div>
<!--<div *ngIf="settingsService.getLocale().startsWith('zh')" class="tab-pane" id="game-replay-bilibili" role="tabpanel">
......
......@@ -9,7 +9,7 @@ import * as $ from 'jquery';
import * as path from 'path';
import 'rxjs/Rx';
import {ISubscription} from 'rxjs/Subscription';
import {App} from './app';
import {App, Category} from './app';
import {AppsService} from './apps.service';
import {LoginService} from './login.service';
import {SettingsService} from './settings.sevices';
......@@ -98,6 +98,7 @@ interface YGOProDistroData {
replayPath: string;
systemConf?: string;
lastDeckFormat?: string;
lastCategoryFormat?: string;
}
interface YGOProData {
......@@ -110,6 +111,12 @@ let matching: ISubscription | undefined;
let matching_arena: string | undefined;
let match_started_at: Date;
interface DeckCategory {
title: string;
decks: string[]
selected?: string;
}
@Component({
moduleId: module.id,
selector: 'ygopro',
......@@ -128,10 +135,12 @@ export class YGOProComponent implements OnInit, OnDestroy, OnChanges {
@Output()
points: EventEmitter<Points> = new EventEmitter();
decks: string[] = [];
categories: DeckCategory[] = [];
replays: string[] = [];
replays2: string[] = [];
current_deck: string;
currentCategory: DeckCategory = { title: '', decks: [], selected: undefined };
currentCategoryDecks: string[] = [];
currentDeck: string;
system_conf: string;
numfont: string[];
textfont: string[];
......@@ -157,6 +166,7 @@ export class YGOProComponent implements OnInit, OnDestroy, OnChanges {
rooms_loading = true;
lastDeckFormat: RegExp;
lastCategoryFormat: RegExp;
default_options: Options = {
mode: 1,
......@@ -339,6 +349,15 @@ export class YGOProComponent implements OnInit, OnDestroy, OnChanges {
this.lastDeckFormat = undefined;
}
// lastCategoryFormat
if (ygoproData.ygopro.lastCategoryFormat) {
// console.log(`Category format pattern: ${ygoproData.ygopro.lastCategoryFormat}`)
this.lastCategoryFormat = new RegExp(ygoproData.ygopro.lastCategoryFormat);
} else {
this.lastCategoryFormat = undefined;
}
// this.lastCategoryFormat = undefined;
this.system_conf = this.app.systemConfPath;
console.log(`Will load system conf file from ${this.system_conf}`);
await this.refresh(true);
......@@ -477,11 +496,12 @@ export class YGOProComponent implements OnInit, OnDestroy, OnChanges {
async refresh(init?: boolean) {
this.decks = await this.get_decks();
this.categories = await this.get_decks();
if (this.lastDeckFormat) {
const systemConfString = await this.load_system_conf();
let lastDeck: string;
let lastCategory: string;
if (systemConfString) {
// console.log(`System conf string: ${systemConfString}`);
const lastDeckMatch = systemConfString.match(this.lastDeckFormat);
......@@ -491,15 +511,33 @@ export class YGOProComponent implements OnInit, OnDestroy, OnChanges {
} else {
// console.error(`Deck pattern not found from pattern ${this.system_conf}: ${lastDeckMatch}`);
}
if (this.lastCategoryFormat) {
const lastCategoryMatch = systemConfString.match(this.lastCategoryFormat);
if (lastCategoryMatch) {
lastCategory = lastCategoryMatch[1];
// console.log(`Last category ${lastCategoryMatch[1]} read from ${this.system_conf}.`);
} else {
// console.error(`Category pattern not found from pattern ${this.system_conf}: ${lastCategoryMatch}`);
}
}
} else {
// console.error(`System conf ${this.system_conf} not found.`);
}
const matchingCategory = this.categories.find(category => category.title === lastCategory);
if (lastDeck && this.decks.includes(lastDeck)) {
// console.log(`Got last deck ${lastDeck}.`);
this.current_deck = lastDeck;
} else if (init) {
this.current_deck = this.decks[0];
if (matchingCategory) {
this.currentCategory = matchingCategory;
} else {
this.currentCategory = this.categories[0];
}
this.currentCategoryDecks = this.currentCategory.decks;
if (this.currentCategoryDecks.includes(lastDeck)) {
this.currentDeck = lastDeck;
} else if (init || !this.currentCategoryDecks.includes(this.currentDeck)) {
this.currentDeck = this.currentCategoryDecks[0];
}
}
......@@ -521,39 +559,49 @@ export class YGOProComponent implements OnInit, OnDestroy, OnChanges {
}
};
async get_decks(): Promise<string[]> {
async get_decks(): Promise<DeckCategory[]> {
try {
/*
const deckPath = this.app.ygoproDeckPath;
let result: string[] = [];
let result: DeckCategory[] = [{
title: '',
decks: [],
}];
const files: string[] = await fs.readdir(deckPath);
for (const file of files) {
if (file.startsWith('.git')) { // fuck
continue;
}
if (path.extname(file) === '.ydk') {
result.push(path.basename(file, '.ydk'));
} else {
result[0].decks.push(path.basename(file, '.ydk'));
} else if (this.lastCategoryFormat) {
const fullPath = path.join(deckPath, file);
const stat = await fs.stat(fullPath);
if (stat.isDirectory()) {
const innerDecks = (await fs.readdir(fullPath))
.filter((iFile) => path.extname(iFile) === '.ydk')
.map((iFile) => path.join(file, path.basename(iFile, '.ydk')));
result = result.concat(innerDecks);
.map((iFile) => path.basename(iFile, '.ydk'));
result.push({
title: file,
decks: innerDecks,
})
}
}
}
return result;
*/
let files: string[] = await fs.readdir(this.app.ygoproDeckPath);
return files.filter(file => path.extname(file) === '.ydk').map(file => path.basename(file, '.ydk'));
} catch (error) {
console.error(`Load deck fail: ${error.toString()}`);
return [];
return [{
title: '',
decks: [],
}];
}
}
refreshCurrentCategoryDecks() {
this.currentCategoryDecks = this.currentCategory.decks;
this.currentDeck = this.currentCategoryDecks[0];
}
async get_replays(): Promise<string[]> {
try {
let files: string[] = await fs.readdir(this.app.ygoproReplayPath);
......@@ -626,27 +674,35 @@ export class YGOProComponent implements OnInit, OnDestroy, OnChanges {
return fs.writeFile(this.system_conf, ini.unsafe(ini.stringify(data, <EncodeOptions>{whitespace: true})));
};*/
async startYGOPro(action: string, param: any) {
if (this.currentCategory.title) {
return this.start_game(`${action}_ex`, { ...param, category: this.currentCategory.title, deck: this.currentDeck });
} else {
return this.start_game(action, { ...param, deck: this.currentDeck });
}
}
async join(name: string, server: Server) {
/*let system_conf = await this.load_system_conf();
await this.fix_fonts(system_conf);
system_conf.lastdeck = this.current_deck;
system_conf.lastdeck = this.currentDeck;
system_conf.lastip = server.address;
system_conf.lasthost = server.address;
system_conf.lastport = server.port.toString();
system_conf.roompass = name;
system_conf.nickname = this.loginService.user.username;
await this.save_system_conf(system_conf);*/
// return this.start_game(['-h', server.address, '-p', server.port.toString(), '-w', name, '-n', this.loginService.user.username, '-d', this.current_deck, '-j']);
return this.start_game('main', {server, password: name, username: this.loginService.user.username, deck: this.current_deck});
// return this.start_game(['-h', server.address, '-p', server.port.toString(), '-w', name, '-n', this.loginService.user.username, '-d', this.currentDeck, '-j']);
return this.startYGOPro('main', {server, password: name, username: this.loginService.user.username});
};
async edit_deck(deck: string) {
async edit_deck() {
/*let system_conf = await this.load_system_conf();
await this.fix_fonts(system_conf);
system_conf.lastdeck = deck;
await this.save_system_conf(system_conf);*/
// return this.start_game(['-d', deck]);
return this.start_game('deck', { deck })
return this.startYGOPro('deck', {})
}
async watch_replay(replay: string) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment