Skip to content

Instantly share code, notes, and snippets.

@valex
Created March 4, 2021 13:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save valex/f675bc3f11e93fad7bc7e7d1751e6ada to your computer and use it in GitHub Desktop.
Save valex/f675bc3f11e93fad7bc7e7d1751e6ada to your computer and use it in GitHub Desktop.
<template>
<v-row>
<v-col :cols="5">
<chessboard-with-controls
:initial-orientation=initialOrientation
></chessboard-with-controls>
<v-card v-if="mounted && $store.getters['users/isAdmin']">
<v-card-text>
<v-text-field
v-model="position_title"
label="Название"
></v-text-field>
<v-textarea
v-model="move_description"
label="Описание последнего хода"
></v-textarea>
<v-textarea
v-model="position_description"
label="Описание позиции"
></v-textarea>
<v-textarea
v-model="position_notes"
label="Заметки"
></v-textarea>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
@click="clickSaveAll"
:loading = "loadings.save_all"
color="error"
>
Save All
</v-btn>
</v-card-actions>
</v-card>
</v-col>
<v-col :cols="7">
<v-card
min-height="66"
outlined
tile
>
<v-card-text>
<v-btn v-for="move in possible_moves" :key="move.san" @click="clickMove(move)" tile depressed small style="text-transform: none;" class="mb-1 mr-1">
{{move.san}}
</v-btn>
</v-card-text>
</v-card>
<v-card tile outlined>
<v-card-title v-if="position_title"><h1 class="headline">{{position_title}}</h1></v-card-title>
<v-card-text v-if="move_description" v-html="move_description"></v-card-text>
<v-divider v-if="move_description"></v-divider>
<v-card-text v-html="position_description"></v-card-text>
</v-card>
</v-col>
</v-row>
</template>
<script lang="js">
import * as firebase from 'firebase/app';
import 'firebase/firestore';
import * as _ from "lodash";
import { mapState } from 'vuex';
import ChessboardWithControls from '~/components/ChessboardWithControls.vue';
import FenHelper from '~/app/helpers/FenHelper';
export default {
name: 'ChessboardPage',
lastMoveRef: null,
props: {
initialOrientation:{ // 'white', 'black'
type: String,
default: 'white'
},
},
components: {
ChessboardWithControls
},
data(context) {
return {
mounted: false,
loadings: {
save_all: false
}
};
},
// Только на стороне сервера
// Будет автоматически вызвано рендером сервера
serverPrefetch () {
// возвращает Promise из действия, поэтому
// компонент ждёт данные перед рендерингом
return this.syncPosition(this.initial_fen);
},
mounted() {
this.mounted = true;
this.$eventBus.$on('move', this.onMove);
this.$eventBus.$on('move-back', this.onHistoryMove);
this.$eventBus.$on('move-forward', this.onHistoryMove);
if(_.isEmpty(this.possible_moves)){
this.syncPosition(this.initial_fen);
}
if(this.addCurrentToFSFromClient){
this.addNewPositionToFS(this.initial_fen).then(()=>{
this.$store.commit('chessboard/SET_ADD_CURRENT_TO_FS', false);
});
}
},
methods: {
async syncPosition( currentFen, fromFen, moveObject){
this.clearPageMeta();
const currentParsedFen = FenHelper.parse(currentFen);
const currentFirestoreFen = _.get(currentParsedFen, 'firestore_fen');
const positionsRef = firebase.firestore().collection("positions");
const currentPositionRef = positionsRef.doc(currentFirestoreFen);
// Add position if not exists
await currentPositionRef.get().then(async (positionSnapshot)=> {
if (positionSnapshot.exists) {
//console.log("Document data:", positionSnapshot.data());
} else {
// positionSnapshot.data() will be undefined in this case
// No such document!
if(process.server){
this.$store.commit('chessboard/SET_ADD_CURRENT_TO_FS', true);
}else{
await this.addNewPositionToFS(currentFen);
}
}
}).catch(function(error) {
console.log("Error getting POSITION document:", error);
});
if( ! _.isNil(fromFen) && ! _.isNil(moveObject)) {
const fromParsedFen = FenHelper.parse(fromFen);
const fromFirestoreFen = _.get(fromParsedFen, 'firestore_fen');
const fromPositionRef = positionsRef.doc(fromFirestoreFen);
const possibleMovesRef = fromPositionRef.collection("possible_moves");
this.$options.lastMoveRef = possibleMovesRef.doc(moveObject.san);
// Add move if not exists
await this.$options.lastMoveRef.get().then((snapshot) => {
if (snapshot.exists) {
const increment = firebase.firestore.FieldValue.increment(1);
this.$options.lastMoveRef.update({ views: increment });
this.$store.commit('chessboard/SET_MOVE_DESCRIPTION', _.get(snapshot.data(), 'description'));
} else {
// snapshot.data() will be undefined in this case
// No such document!
this.$options.lastMoveRef.set({
views: 0,
...moveObject
} )
}
}).catch(function(error) {
console.log("Error getting MOVE document:", error);
});
}
// GET DATA FOR CURRENT POSITION
const positionSnap = await currentPositionRef.get();
if( ! positionSnap.exists )
return;
const movesSnap = await currentPositionRef
.collection("possible_moves")
.orderBy("views", "desc").get();
let movesFromSnap = [];
movesSnap.forEach((move) =>{
// doc.data() is never undefined for query doc snapshots
movesFromSnap.push(move.data())
});
this.possible_moves = movesFromSnap;
const positionData = positionSnap.data();
// setup shapes
if( ! _.isEmpty(positionData.shapes)){
this.shapes = positionData.shapes;
}
this.position_title = positionData.name;
this.position_description = positionData.description;
this.position_notes = positionData.notes;
this.saveHistoryMeta(fromFen, moveObject);
},
addNewPositionToFS(fen){
const parsedFen = FenHelper.parse(fen);
return firebase.firestore()
.collection("positions")
.doc(_.get(parsedFen, 'firestore_fen'))
.set({
fen: ''+_.get(parsedFen, 'valuable_fen'),
move_number: +_.get(parsedFen, 'move_number'),
shapes: []
});
},
async clickSaveAll() {
this.$eventBus.$emit('sync-chessground-state');
let vuexShapes = this.$store.state.chessboard.chessgroundState.shapes;
let shapes = _.map(vuexShapes, shape=>{
return _.pickBy(shape, (value, key) => {
if( _.isUndefined(value))
return false;
return _.includes(['orig', 'dest', 'brush', 'modifiers'], key);
});
});
this.loadings.save_all=true;
await this.saveShapes(shapes);
await this.savePositionMeta();
await this.saveLastMoveMeta();
this.loadings.save_all=false;
},
saveLastMoveMeta(){
if( _.isNil(this.$options.lastMoveRef) ){
console.error('this.$options.lastMoveRef not set. Move Description not save');
return;
}else{
this.$options.lastMoveRef.update({
description: this.move_description || null,
});
}
},
savePositionMeta(){
const currentFen = this.$store.state.chessboard.chessgroundState.fen;
const currentParsedFen = FenHelper.parse(currentFen);
const currentFirestoreFen = _.get(currentParsedFen, 'firestore_fen');
const currentPositionRef = firebase.firestore().collection("positions").doc(currentFirestoreFen);
return currentPositionRef.update({
name: this.position_title || null,
description: this.position_description || null,
notes: this.position_notes || null,
});
},
saveShapes(shapes) {
const currentFen = this.$store.state.chessboard.chessgroundState.fen;
const currentParsedFen = FenHelper.parse(currentFen);
const currentFirestoreFen = _.get(currentParsedFen, 'firestore_fen');
const currentPositionRef = firebase.firestore().collection("positions").doc(currentFirestoreFen);
return currentPositionRef.update({
shapes: shapes,
});
},
clickMove(moveObject) {
this.$eventBus.$emit('make-move', moveObject);
},
onMove(currentFen, fromFen, moveObject){
this.syncPosition(currentFen, fromFen, moveObject);
},
onHistoryMove() {
this.clearPageMeta();
this.applyHistoryMeta();
},
saveHistoryMeta(fromFen, moveObject){
let from_firestore_fen = null;
let last_move_san = null;
if( ! _.isNil(fromFen) && ! _.isNil(moveObject)) {
from_firestore_fen = _.get(FenHelper.parse(fromFen), 'firestore_fen');
last_move_san = moveObject.san;
}
this.meta_history = {
from_firestore_fen,
last_move_san,
possible_moves: this.possible_moves,
position_title: this.position_title,
position_description: this.position_description,
position_notes: this.position_notes,
move_description: this.move_description,
shapes: this.shapes,
};
},
applyHistoryMeta(){
if( _.isNil(this.meta_history[this.historyMetaPointer]))
return;
if( ! _.isNil(this.meta_history[this.historyMetaPointer]['from_firestore_fen']) &&
! _.isNil(this.meta_history[this.historyMetaPointer]['last_move_san']))
{
this.$options.lastMoveRef = firebase.firestore()
.collection("positions")
.doc(this.meta_history[this.historyMetaPointer]['from_firestore_fen'])
.collection("possible_moves")
.doc(this.meta_history[this.historyMetaPointer]['last_move_san']);
}
this.possible_moves = this.meta_history[this.historyMetaPointer]['possible_moves'];
this.position_title = this.meta_history[this.historyMetaPointer]['position_title'];
this.position_description = this.meta_history[this.historyMetaPointer]['position_description'];
this.position_notes = this.meta_history[this.historyMetaPointer]['position_notes'];
this.move_description = this.meta_history[this.historyMetaPointer]['move_description'];
this.shapes = this.meta_history[this.historyMetaPointer]['shapes'];
},
clearPageMeta() {
this.$options.lastMoveRef = null;
this.possible_moves = [];
this.position_title = '';
this.position_description = '';
this.position_notes = '';
this.move_description = '';
}
},
computed: {
position_title: {
get () {
return this.$store.state.chessboard.position_title
},
set (value) {
this.$store.commit('chessboard/SET_POSITION_TITLE', value);
}
},
position_description: {
get () {
return this.$store.state.chessboard.position_description
},
set (value) {
this.$store.commit('chessboard/SET_POSITION_DESCRIPTION', value);
}
},
position_notes:{
get () {
return this.$store.state.chessboard.position_notes
},
set (value) {
this.$store.commit('chessboard/SET_POSITION_NOTES', value);
}
},
move_description: {
get () {
return this.$store.state.chessboard.move_description
},
set (value) {
this.$store.commit('chessboard/SET_MOVE_DESCRIPTION', value);
}
},
possible_moves: {
get () {
return this.$store.state.chessboard.possible_moves
},
set (value) {
this.$store.commit('chessboard/SET_POSSIBLE_MOVES', value);
}
},
shapes:{
get () {
return this.$store.state.chessboard.shapes
},
set (value) {
this.$store.commit('chessboard/SET_SHAPES', value);
}
},
meta_history:{
get () {
return this.$store.state.chessboard.pageMetaHistory
},
set (value) {
this.$store.commit('chessboard/SET_PAGE_META_HISTORY', {
index:this.historyMetaPointer,
value
}
);
}
},
historyMetaPointer(){
return 1 + this.historyMovesPointer;
},
...mapState({
initial_fen: state => state.chessboard.initial_fen,
historyMovesPointer: state => state.chessboard.historyMovesPointer,
addCurrentToFSFromClient: state => state.chessboard.addCurrentToFSFromClient,
})
},
}
</script>
<style scoped>
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment