Commit e793f813 authored by 神楽坂玲奈's avatar 神楽坂玲奈

room filter

parent 6fe166b3
环境: <mat-form-field appearance='standard'> 环境:
<!-- <mat-label>Favorite food</mat-label>--> <mat-form-field appearance='standard'>
<mat-select [(ngModel)]='ygopro.currentServer'> <mat-select [formControl]='ygopro.serverForm'>
<mat-option *ngFor='let server of ygopro.selectableServers' [value]='server'> <mat-option *ngFor='let server of ygopro.selectableServers' [value]='server'>
{{server.name}} {{server.name}}
</mat-option> </mat-option>
......
...@@ -8,8 +8,6 @@ import { YGOProService } from '../ygopro.service'; ...@@ -8,8 +8,6 @@ import { YGOProService } from '../ygopro.service';
}) })
export class ServerSelectComponent implements OnInit { export class ServerSelectComponent implements OnInit {
//servers = [{ id: 'mycard', name: '标准' }, { id: 'test', name: '测试' }];
constructor(public ygopro: YGOProService) { constructor(public ygopro: YGOProService) {
} }
......
...@@ -9,8 +9,9 @@ import { MatchDialogComponent } from './match-dialog/match-dialog.component'; ...@@ -9,8 +9,9 @@ import { MatchDialogComponent } from './match-dialog/match-dialog.component';
import { ResultDialogComponent } from './result-dialog/result-dialog.component'; import { ResultDialogComponent } from './result-dialog/result-dialog.component';
import { StorageService } from './storage.service'; import { StorageService } from './storage.service';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { catchError, filter, map, mergeMap, publishLast, refCount, scan, startWith } from 'rxjs/internal/operators'; import { catchError, filter, map, mergeMap, publishLast, refCount, scan, startWith, switchMap, tap } from 'rxjs/internal/operators';
import { webSocket } from 'rxjs/webSocket'; import { webSocket } from 'rxjs/webSocket';
import { FormControl } from '@angular/forms';
export interface User { export interface User {
admin: boolean; admin: boolean;
...@@ -120,6 +121,7 @@ export class YGOProService { ...@@ -120,6 +121,7 @@ export class YGOProService {
news: Promise<News[]>; news: Promise<News[]>;
topics: Promise<any[]>; topics: Promise<any[]>;
points = new BehaviorSubject<Points | undefined>(undefined); points = new BehaviorSubject<Points | undefined>(undefined);
serverForm = new FormControl();
readonly default_options: Options = { readonly default_options: Options = {
mode: 1, mode: 1,
...@@ -140,33 +142,19 @@ export class YGOProService { ...@@ -140,33 +142,19 @@ export class YGOProService {
selectableServers: Server[] = []; selectableServers: Server[] = [];
currentServer: Server; currentServer: Server;
reloadSelectableServers(condition: (server: Server) => boolean = () => true) {
this.selectableServers = this.servers.filter(s => {
if (s.hidden) {
return false;
}
return condition(s);
});
if(!this.currentServer || !this.selectableServers.includes(this.currentServer)) {
this.currentServer = this.selectableServers[0];
}
}
constructor(private login: LoginService, private http: HttpClient, private dialog: MatDialog, private storage: StorageService) { constructor(private login: LoginService, private http: HttpClient, private dialog: MatDialog, private storage: StorageService) {
const app = this.http.get<App[]>('https://sapi.moecube.com:444/apps.json').pipe(map(apps => apps.find(_app => _app.id === 'ygopro')!), publishLast(), refCount()); const app = this.http.get<App[]>('https://sapi.moecube.com:444/apps.json').pipe(
map(apps => apps.find(_app => _app.id === 'ygopro')!),
publishLast(),
refCount()
);
this.serversPromise = app this.serversPromise = app.pipe(map(_app => _app.data.servers)).toPromise();
.pipe(
map(_app =>
_app.data.servers
)
)
.toPromise();
this.serversPromise.then((servers) => { this.serversPromise.then(servers => {
this.servers = servers; this.servers = servers;
this.reloadSelectableServers(); this.reloadSelectableServers();
}) });
this.news = app this.news = app
.pipe( .pipe(
...@@ -257,6 +245,19 @@ export class YGOProService { ...@@ -257,6 +245,19 @@ export class YGOProService {
}); });
} }
reloadSelectableServers(condition: (server: Server) => boolean = () => true) {
this.selectableServers = this.servers.filter(s => {
if (s.hidden) {
return false;
}
return condition(s);
});
if (!this.currentServer || !this.selectableServers.includes(this.currentServer)) {
this.currentServer = this.selectableServers[0];
this.serverForm.setValue(this.currentServer);
}
}
async request_match(arena: string) { async request_match(arena: string) {
const data = await this.dialog const data = await this.dialog
.open(MatchDialogComponent, { data: arena, disableClose: true }) .open(MatchDialogComponent, { data: arena, disableClose: true })
...@@ -270,15 +271,14 @@ export class YGOProService { ...@@ -270,15 +271,14 @@ export class YGOProService {
create_room(room: Room, host_password: string) { create_room(room: Room, host_password: string) {
const options_buffer = Buffer.alloc(6); const options_buffer = Buffer.alloc(6);
// 建主密码 https://docs.google.com/document/d/1rvrCGIONua2KeRaYNjKBLqyG9uybs9ZI-AmzZKNftOI/edit // 建主密码 https://docs.google.com/document/d/1rvrCGIONua2KeRaYNjKBLqyG9uybs9ZI-AmzZKNftOI/edit
options_buffer.writeUInt8(((room.private ? 2 : 1) << 4) | options_buffer.writeUInt8(((room.private ? 2 : 1) << 4) | (room.options.duel_rule << 1) | (room.options.auto_death ? 0x1 : 0), 1);
(room.options.duel_rule << 1) |
(room.options.auto_death ? 0x1 : 0), 1);
options_buffer.writeUInt8( options_buffer.writeUInt8(
room.options.rule << 5 | (room.options.rule << 5) |
room.options.mode << 3 | (room.options.mode << 3) |
(room.options.no_check_deck ? 1 << 1 : 0) | (room.options.no_check_deck ? 1 << 1 : 0) |
(room.options.no_shuffle_deck ? 1 : 0) (room.options.no_shuffle_deck ? 1 : 0),
, 2); 2
);
options_buffer.writeUInt16LE(room.options.start_lp, 3); options_buffer.writeUInt16LE(room.options.start_lp, 3);
options_buffer.writeUInt8((room.options.start_hand << 4) | room.options.draw_count, 5); options_buffer.writeUInt8((room.options.start_hand << 4) | room.options.draw_count, 5);
let checksum = 0; let checksum = 0;
...@@ -287,7 +287,7 @@ export class YGOProService { ...@@ -287,7 +287,7 @@ export class YGOProService {
} }
options_buffer.writeUInt8(checksum & 0xff, 0); options_buffer.writeUInt8(checksum & 0xff, 0);
const secret = this.login.user.external_id % 65535 + 1; const secret = (this.login.user.external_id % 65535) + 1;
for (let i = 0; i < options_buffer.length; i += 2) { for (let i = 0; i < options_buffer.length; i += 2) {
options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i); options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i);
} }
...@@ -314,7 +314,7 @@ export class YGOProService { ...@@ -314,7 +314,7 @@ export class YGOProService {
} }
options_buffer.writeUInt8(checksum & 0xff, 0); options_buffer.writeUInt8(checksum & 0xff, 0);
const secret = this.login.user.external_id % 65535 + 1; const secret = (this.login.user.external_id % 65535) + 1;
for (let i = 0; i < options_buffer.length; i += 2) { for (let i = 0; i < options_buffer.length; i += 2) {
options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i); options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i);
} }
...@@ -333,7 +333,7 @@ export class YGOProService { ...@@ -333,7 +333,7 @@ export class YGOProService {
} }
options_buffer.writeUInt8(checksum & 0xff, 0); options_buffer.writeUInt8(checksum & 0xff, 0);
const secret = this.login.user.external_id % 65535 + 1; const secret = (this.login.user.external_id % 65535) + 1;
for (let i = 0; i < options_buffer.length; i += 2) { for (let i = 0; i < options_buffer.length; i += 2) {
options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i); options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i);
} }
...@@ -425,6 +425,7 @@ export class YGOProService { ...@@ -425,6 +425,7 @@ export class YGOProService {
alert(JSON.stringify({ method: 'share', params: [text] })); alert(JSON.stringify({ method: 'share', params: [text] }));
} }
} }
isRoomAvailableToDisplay(r: Room) { isRoomAvailableToDisplay(r: Room) {
return (r.arena && this.currentServer && this.currentServer.id === 'tiramisu') || r.server === this.currentServer; return (r.arena && this.currentServer && this.currentServer.id === 'tiramisu') || r.server === this.currentServer;
} }
...@@ -448,28 +449,33 @@ export class RoomListDataSource extends DataSource<Room> { ...@@ -448,28 +449,33 @@ export class RoomListDataSource extends DataSource<Room> {
/** Connect function called by the table to retrieve one stream containing the data to render. */ /** Connect function called by the table to retrieve one stream containing the data to render. */
connect(): Observable<Room[]> { connect(): Observable<Room[]> {
this.loading.emit(true); this.loading.emit(true);
return combineLatest(
this.ygopro.servers.filter(s => s.url && (s.custom || s.replay)).map(server => { return this.ygopro.serverForm.valueChanges.pipe(
const url = new URL(server.url!); this.ygopro.serverForm.value ? startWith(this.ygopro.serverForm.value) : tap(),
url.searchParams.set('filter', this.type); switchMap(env =>
// 协议处理 combineLatest(
return webSocket<Message>(url.toString()).pipe( [env].filter(s => s.url && (s.custom || s.replay)).map(server => {
scan((rooms: Room[], message: Message, index: number) => { const url = new URL(server.url!);
switch (message.event) { url.searchParams.set('filter', this.type);
case 'init': // 协议处理
return message.data.map(room => ({ server: server, ...room })); return webSocket<Message>(url.toString()).pipe(
case 'create': scan((rooms: Room[], message: Message, index: number) => {
return rooms.concat({ server: server, ...message.data }); switch (message.event) {
case 'update': case 'init':
Object.assign(rooms.find(room => room.id === message.data.id), message.data); return message.data.map(room => ({ server: server, ...room }));
return rooms; case 'create':
case 'delete': return rooms.concat({ server: server, ...message.data });
return rooms.filter(room => room.id !== message.data); case 'update':
} Object.assign(rooms.find(room => room.id === message.data.id), message.data);
}, []) return rooms;
); case 'delete':
}) return rooms.filter(room => room.id !== message.data);
).pipe( }
}, [])
);
})
)
),
// 把多个服务器的数据拼接起来 // 把多个服务器的数据拼接起来
map((sources: Room[][]) => (<Room[]>[]).concat(...sources)), map((sources: Room[][]) => (<Room[]>[]).concat(...sources)),
// 筛选一下房间,只扔进去当前房间或者竞技匹配的 // 筛选一下房间,只扔进去当前房间或者竞技匹配的
...@@ -489,10 +495,9 @@ export class RoomListDataSource extends DataSource<Room> { ...@@ -489,10 +495,9 @@ export class RoomListDataSource extends DataSource<Room> {
}) })
), ),
// loading、empty、error // loading、empty、error
filter(rooms => { tap(rooms => {
this.loading.emit(false); this.loading.emit(false);
this.empty.emit(rooms.length === 0); this.empty.emit(rooms.length === 0);
return true;
}), }),
catchError(error => { catchError(error => {
this.loading.emit(false); this.loading.emit(false);
......
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