Alt-Org / Altzone-Server

REST API
4 stars 1 forks source link

add /playerTasks GET endpoint for retrieving player's tasks #203

Closed MikhailDeriabin closed 1 week ago

MikhailDeriabin commented 1 week ago

Swagger

Flow chart

Predefined tasks table

Notice that tasks are predefined and are same for each player and should come from a JSON file, structure of which you can find in flowchart. Therefore I think this file should be just loaded to RAM and not stored in DB. These tasks can be changed over time via this file and therefore make sure not to hard code anything. Currently there are no differences between tasks for Monday, Tuesday etc. so just put the same tasks for each day (3 played battles, 5 won battles etc.). I am not sure will be there any tasks for week1, week2, month1 etc. so you can just add one array for weekly tasks and one for monthly tasks.

You can add all of the tasks from the table or just those that can be tracked at the time, which are play battle, win battle and send chat message. Other tasks you can not implement yet.

You can also read general description in the milestone.

PlayJeri commented 1 week ago

@MikhailDeriabin

The GET /playerTasks endpoint can't really be implemented until the db schema and tracking logic is defined. Maybe this part should be converted to a new issue. So if we start with the JSON file and loading that file into ram and then separate the endpoint to a new issue.

I have done the logic for that and published the branch. Now we have to decide where to store this .json file and how to include it in the build. The file is now located in the src/playerTasks folder and I added it as asset in nest-cli.json and ts.configs include but I'm not sure if this is the best way to do this.

But my suggestion is that we start with this json file and it's logic and figure out the endpoint later.

I also added the .vscode folder to .gitignore

MikhailDeriabin commented 1 week ago

@PlayJeri

GET endpoint

Yes, I see you. Sure we can separate the GET endpoint task to another issue. I just thought that you might need to check that the tracking logic works when you implement it with this endpoint.

JSON file structure

The tasks should be separate arrays for each week day Monday, Tuesday etc. not just daily. They are not really defined now but they gonna be a bit different for each day. For example for Monday "win 10 battles" and for Tuesday: "win 3 battles". For now you can just duplicate that daily array for each day, which is a sub-optimal, but there are nothing we can do about it:

"monday": [
    {
      "id": 1,
      "title": { "fi": "Pelaa 3 taistelua" },
      "content": { "fi": "Sun pitää pelata tänään 3 taistelua" },
      "amount": 3,
      "type": "play_battle",
      "coins": 30,
      "points": 60
    },
    {
      "id": 2,
      "title": { "fi": "Voita 5 taistelua" },
      "content": { "fi": "Sun pitää voittaa tänään 5 taistelua" },
      "amount": 5,
      "type": "win_battle",
      "coins": 250,
      "points": 500
    },
    {
      "id": 3,
      "title": { "fi": "Lähetä 10 viestiä chattiin" },
      "content": { "fi": "Sun pitää lähettää tänään 10 viestiä chattiin" },
      "amount": 10,
      "type": "write_chat_message",
      "coins": 45,
      "points": 90
    },
    {
      "id": 4,
      "title": { "fi": "Aloita taistelu eri hahmolla" },
      "content": { "fi": "Sun pitää aloittaa taistelu eri hahmolla" },
      "amount": 3,
      "type": "start_battle_with_new_character",
      "coins": 30,
      "points": 60
    },
    {
      "id": 5,
      "title": { "fi": "Äänestä 2 kertaa" },
      "content": { "fi": "Sun pitää äänestää tänään 2 kertaa" },
      "amount": 2,
      "type": "vote",
      "coins": 20,
      "points": 40
    }
  ],
  "tuesday": [
    {
      "id": 1,
      "title": { "fi": "Pelaa 3 taistelua" },
      "content": { "fi": "Sun pitää pelata tänään 3 taistelua" },
      "amount": 3,
      "type": "play_battle",
      "coins": 30,
      "points": 60
    },
    {
      "id": 2,
      "title": { "fi": "Voita 5 taistelua" },
      "content": { "fi": "Sun pitää voittaa tänään 5 taistelua" },
      "amount": 5,
      "type": "win_battle",
      "coins": 250,
      "points": 500
    },
    {
      "id": 3,
      "title": { "fi": "Lähetä 10 viestiä chattiin" },
      "content": { "fi": "Sun pitää lähettää tänään 10 viestiä chattiin" },
      "amount": 10,
      "type": "write_chat_message",
      "coins": 45,
      "points": 90
    },
    {
      "id": 4,
      "title": { "fi": "Aloita taistelu eri hahmolla" },
      "content": { "fi": "Sun pitää aloittaa taistelu eri hahmolla" },
      "amount": 3,
      "type": "start_battle_with_new_character",
      "coins": 30,
      "points": 60
    },
    {
      "id": 5,
      "title": { "fi": "Äänestä 2 kertaa" },
      "content": { "fi": "Sun pitää äänestää tänään 2 kertaa" },
      "amount": 2,
      "type": "vote",
      "coins": 20,
      "points": 40
    }
  ],
  ...

JSON file and Nest

Yes, the place for the playerTasks.json file should be in playerTasks. I think your solution with nest-cli.json is good, I think it is a common way to do it in Nest.

PlayJeri commented 1 week ago

@MikhailDeriabin

The service will need some type of CRON job to update the tasks while server is running. I was thinking about using this package. https://docs.nestjs.com/techniques/task-scheduling

Then implement the daily, weekly and monthly updates.

Just making sure it's okay to add this dependency

MikhailDeriabin commented 1 week ago

@PlayJeri I am not sure why do you need the cron job for it.

You have the PlayerTasks collection, which holds data about when tasks are started and finished. So for example you have a task to win 3 games on Monday. When you register the won game by the Player, you also check whenever the task is already completed or not as well as when it was started:

Or what kind of updates do you mean?

PlayJeri commented 1 week ago

@MikhailDeriabin

This was my idea. So the server would hold only one day, week and month tasks at the time. If the json file holds different tasks for odd and even numbered weeks and months and so on. But I think you are right and this is unnecessary.

private loadTasks() {
    const filePath = path.join(__dirname, 'playerTasks.json');
    const fileContent = fs.readFileSync(filePath, 'utf-8');
    const allTasks = JSON.parse(fileContent);

    const currentDay = new Date().toLocaleDateString('en-US', { weekday: 'long' }).toLowerCase();

    this.tasks = {
      [currentDay]: allTasks[currentDay],
      weekly: allTasks.weekly,
      monthly: allTasks.monthly
    };
  }

  @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT)
  handleDailyUpdate() {
    this.loadTasks();
  }

  @Cron(CronExpression.EVERY_WEEK)
  handleWeeklyUpdate() {
    this.loadTasks();
  }

  @Cron(CronExpression.EVERY_1ST_DAY_OF_MONTH_AT_MIDNIGHT)
  handleMonthlyUpdate() {
    this.loadTasks();
  }
MikhailDeriabin commented 1 week ago

@PlayJeri

Yes, for now it will be enough to implement logic for different week days + weekly + monthly tasks.

When I was trying to plan how the update logic would look like for odd / even weeks, I also did not find any solution except for the cron jobs, but this can add overhead for DB if we have a lot of players. I guess there should some smart algorithm for that, but I could not think about it.

I think that for now it is alright to add a bit simpler logic and test that players actually care about these tasks at all. If they don't then all work with player tasks will be useless. This is why I try to make things as simple as possible in this project, there are always gonna be some changes...