Aiuto per la progettazione di un plugin di integrazione personalizzato

Ciao a tutti! Sto facendo ricerche su diverse piattaforme forum per costruire una community per programmatori competitivi (CP) brasiliani, ma sembra che l’abbia trovata!

Una funzionalità che vorrei avere su questo forum è l’integrazione con Codeforces, una piattaforma online che ospita gare e discussioni su CP. All’interno di Codeforces, i partecipanti hanno un rating che cambia in base alla loro performance nelle gare classificate. Vorrei dare ai miei utenti la possibilità di visualizzare i loro faticosamente guadagnati rating sul profilo del forum.

La prima cosa che questo plugin che voglio sviluppare dovrebbe fare, quindi, è permettere all’utente di inserire il proprio handle Codeforces e poi autenticare in qualche modo che l’handle appartenga all’utente del forum. Per farlo, sto pensando di utilizzare il plugin Custom Wizard per chiedere l’handle, quindi inviare una stringa casuale tramite l’API Codeforces Talks che l’utente dovrà reinserire correttamente e, se tutto è ok, salvare l’handle in un campo utente personalizzato. Ti sembra ragionevole? Lo faresti diversamente?

Ora, conosco i miei utenti [futuri], dopotutto sono anch’io un CPer! Apprezzerebbero visualizzare il proprio rating attraverso il colore dell’handle del forum. Cioè, se hai un rating superiore a 1400, l’handle sarà ciano; se è superiore a 1600, sarà blu, e così via.

La mia rapida ricerca su come personalizzare i colori degli handle su Discourse mi ha portato alla seguente soluzione. Dovrei creare un gruppo utente per ogni fascia di rating e poi assegnare dinamicamente i miei utenti al gruppo corretto. (C’è un modo migliore o più semplice?)

Quindi, quando l’utente collega inizialmente il proprio account Codeforces al proprio profilo, potrei recuperare il suo rating e assegnargli il gruppo corretto (specialist, expert, candidate master, …, international grandmaster). Tuttavia, il rating potrebbe cambiare presto e vorrei aggiornare automaticamente il gruppo dell’utente quando il suo rating cambia.

Ora, ho pensato a diversi modi per raggiungere questo obiettivo e vorrei suggerimenti su quale seguire e, se possibile, alcune indicazioni sulle specificità di Discourse:

  • Avere un Job in esecuzione regolare che aggiorna il rating e il gruppo di ogni utente (molte richieste esterne all’API di Codeforces)
  • Avere un Job in esecuzione regolare che elabora le gare man mano che accadono. Poiché i rating possono cambiare solo durante una gara, se i rating degli utenti sono inizialmente coerenti, elaborando le variazioni di rating man mano che accadono posso aggiornare solo i rating cambiati e mantenere la coerenza con una singola chiamata all’API esterna
  • Avere un risolutore personalizzato per rating e gruppi. Dovrei quindi memorizzare l’ultima acquisizione del rating e, alla prossima richiesta GET rating/groups, se il rating è obsoleto, chiamerei l’API di Codeforces e aggiornerrei il rating/gruppo dell’utente. Questa è la mia soluzione preferita perché sembra semplice e sarà sempre eventualmente coerente. Tuttavia, non sono così sicuro di come implementarla o delle conseguenze dell’aggiunta e rimozione dinamica di un gruppo a un utente. O anche se è possibile affatto come plugin.

Beh, mi scuso per il muro di testo! Mi farebbe piacere ricevere qualsiasi tipo di feedback su tutto questo. Grazie per l’attenzione.

Una volta ottenuto il loro handle di Codeforces in un user_custom_field, sarà abbastanza semplice aggiornare tutto ciò che desideri dal loro profilo (assegnare gruppi, inserire dati del profilo da Codeforces nei campi personalizzati dell’utente e così via) quando effettuano l’accesso.

Qualcosa del genere:

after_initialize do
  DiscourseEvent.on(:user_logged_in) do |user|
    # ottieni dati da Codeforces
      if codeforce_rating > 1400
          group = Group.find_by(name: group_1400)
          if group
            gu = GroupUser.find_by(group_id: group.id, user_id: user.id)
            GroupUser.create(group_id: group.id, user_id: user.id) unless gu
          end
        end
      end

  end

end

In questo modo è davvero semplice e aggiornerai i dati solo per le persone che sono effettivamente attive nella community.

Che bello! Sono contento di aver chiesto in giro prima di implementare qualsiasi cosa.

Grazie mille!

Se tutti i tuoi utenti sono utenti di Codeforces, implementerei un single sign-on (dove Codeforces funge da provider di autenticazione). In questo modo non è necessario alcun passaggio di autenticazione aggiuntivo e i tuoi utenti avranno anche un flusso di registrazione/autenticazione migliore. Potresti persino sincronizzare i gruppi in questo modo!

Lo farei dalla fonte, ovvero quando Codeforces rileva che il rating è cambiato, dovrebbe effettuare una chiamata API verso Discourse per aggiornare il rating (o qualsiasi altra proprietà dell’utente influenzata da tale rating). In questo modo tutto sarà sempre aggiornato. Quando devi sincronizzare dati, il polling porta sempre a problemi in un modo o nell’altro, quindi evitalo dove possibile e utilizza un approccio basato sugli eventi.

Ho presunto che non fosse possibile utilizzare Codeforces come master SSO. Se lo è, vuoi assolutamente farlo in questo modo!

L’assunzione di @pfaffman secondo cui non fosse possibile utilizzare Codeforces come provider di autenticazione era corretta. Codeforces è sostanzialmente mantenuto da una sola persona e dubito che implementerebbe qualcosa per un progetto che si trova ancora in fase di pianificazione/raccolta fondi.

Concordo che il polling sia subottimale! Per questo motivo la soluzione proposta di interrogarlo quando l’utente effettua il login sembra essere un buon compromesso tra [l’interesse dell’utente di] coerenza e il non sovraccaricare i server di Codeforces al punto da attirare l’attenzione e rischiare di essere bloccati.

Se il nostro caso specifico per la comunità brasiliana avrà successo e altre comunità proveranno a fare lo stesso, forse Mike (l’unica persona responsabile di Codeforces) implementerà qualcosa di simile.

Comunque, grazie mille per i suggerimenti! Li terrò a mente per la prossima volta che incontrerò Mike a giugno dell’anno prossimo, quando potrò provare a convincerlo a dare una mano e, eventualmente, ottimizzare la soluzione che il nostro forum potrebbe utilizzare all’epoca.