Esfinge Gamification


Dependência do framework

O Esfinge Gamification está disponível no Maven Central

Visão geral


O Esfinge Gamification é um framework baseado em metadados aplicável aos sistemas que necessitam de uma lógica gamification, independentemente do seu domínio. O principal objetivo do framework é dissociar as preocupações de gamification da aplicação, permitindo que os desenvolvedores se concentrem na lógica da aplicação, acrescentando apenas informação sobre como a gamification deve trabalhar em cada funcionalidade invocada. O framework intercepta estas invocações e executa a lógica gamification apropriada, este também fornece pontos de extensão que permitem a introdução de comportamentos gamification específicos da aplicação.

O Esfinge Gamification define vários tipos de conquistas e diferentes implementações para armazenar informações gamification sobre os usuários. Para registrar como a gamification deve ser manuseada na aplicação, o framework usa anotações que devem ser adicionadas aos métodos de negócio nas classes de aplicação. O framework proposto pode ser facilmente integrado em qualquer aplicação Java, sendo responsável por registrar as conquistas do usuário sem depender de qualquer informação relacionada com o domínio específico da aplicação. Ele fornece também uma API que pode ser acessada diretamente pelo aplicativo para recuperar e mostrar informações relacionadas com as conquistas do usuário, tais como sua pontuação ou sua posição no ranking.

Instanciando o framework

O objetivo desta subseção é apresentar as medidas necessárias para instanciar o Esfinge Gamification em um aplicativo.
O primeiro passo é configurar a classe que deve ser usada para armazenar a informação gamification e o atual usuário. O código a seguir apresenta um exemplo de como isso deve ser feito. A instância configurada deve estender a classe abstrata Game. O framework fornece algumas implementações que armazenam essas informações em arquivos, em memória e em um banco de dados; no entanto, o aplicativo pode criar sua própria implementação para ele. Este exemplo é configurado chamando o método setGame() no GameInvoker.

//configure game
Game g = new GameMemoryStorage();
GameInvoker.getInstance().setGame(g);
//current user
UserStorage.setUserID("spider");

Outra configuração importante apresentada no código anterior é o usuário atual. O método setUserID() na classe UserStorage deve ser chamado para configurar o usuário e para ser usado pelo framework na thread atual. Assim, todos os métodos invocados na thread atual que desencadeiam a lógica gamification usarão este usuário como uma referência. O parâmetro deve ser qualquer identificação do usuário, este será utilizado para fins de armazenamento e de recuperação dos dados. Por exemplo, para criar uma instância do framework em uma aplicação web, um filtro web deve ser criado para configurar o usuário atual em cada solicitação recebida.

O próximo passo é adicionar as anotações gamification adequadas sobre as interfaces dos aplicativos. Os métodos escolhidos para serem anotados devem representar a ação no domínio do aplicativo que deve acionar a lógica gamification. O código a seguir ilustra o uso da anotação @PointsToUser. Com base na configuração, quando uma implementação do método answerQuestion() é invocado, o framework gamification deve adicionar 10 pontos de resposta para o usuário atual. É importante ressaltar que existem outras anotações fornecidos pela estrutura, e também um ponto de extensão que permite a criação de anotações personalizadas.

public interface Questionnaire {
@PointsToUser(name = "ANSWER", quantity = 10)
public void answerQuestion(String answer);
}
O passo final para instanciar o framework é permitir a interceptação dos métodos de invocação da aplicação. Esfinge Gamification funciona com proxies dinâmicos que encapsulam as classes da aplicação para introduzir a invocação da lógica gamification com base nas anotações configuradas. Para criar o proxy, o método createProxy() da classe GameProxy deve ser invocado. Ele recebe uma instância da implementação e retorna um proxy dinâmico que implementa todas as suas interfaces. O código a seguir apresenta um exemplo de como isso deve ser feito. É aconselhável encapsular essa lógica de criação de uma classe factory.


Questionnaire q = (Questionnaire) GameProxy.createProxy(new
QuestionnaireImpl());

Para finalizar, o aplicativo pode usar a API do framework para acessar diretamente os dados gamification. Esta API está disponível através da implementação do classe Game, que pode ser recuperada usando o comando GameInvoker.getInstance().getGame(). Quando o aplicativo precisar de informações gamification, esta deve ser a única lógica de negócios que tem acesso direto ao framework.

Estrutura interna

Sobre como implementar os modelos

Tipos de conquistas

O framework usa um sistema de recompensa no qual o usuário pode receber um certo tipo de conquista quando uma tarefa é executada ou realizada no aplicativo. Conforme ilustrado na figura abaixo, no Esfinge Gamification, quatro tipos de conquistas podem ser encontradas: Ponto, Classificação, Recompensa e Troféu. A interface Achievement também pode ser estendida para incluir outros tipos de recompensas.

 

O tipo Ponto representa um affordance que contém uma medida de número discreto, tais como pontos ou moedas, que podem ser utilizados para alcançar outras conquistas, ou para usar dentro do próprio sistema. O mesmo sistema pode ter diferentes tipos de Ponto. O tipo Ranking representa um nível de usuário escalar (semelhante a uma hierarquia militar), e é descrito por dois atributos, um nome e um nível. Ele pode ser usado para explicar a melhoria de alguma tarefa do usuário ou representar o seu status. Por exemplo, quando uma tarefa é concluída com êxito um certo número de vezes, o usuário pode subir um nível naquela habilidade. Isso incentiva o usuário a explorar as tarefas a serem realizadas e também melhorar o trabalho realizado.

A conquista de Recompensa representa algo que o usuário ganha e pode gastar. As suas características são um nome e uma variável booleana que indica se a Recompensa já foi usada. O usuário mantém esta Recompensa até que ele decida usá-la para algum propósito. Por exemplo, se a Recompensa é um cupom de desconto, ele estará disponível até que o usuário o utilize. O tipo Troféu, que é semelhante ao de distintivos, como no mundo real, descreve um prêmio recebido apenas uma vez. O usuário pode receber um Troféu para a realização de uma tarefa, mas ele não vai ganhar de novo se ele repetir a mesma tarefa.

Novos tipos de realizações podem ser adicionados ao implementar a interface Achievement. Esta interface possui métodos para definir o que deve ser feito quando uma nova conquista desse tipo é adicionado para um usuário. A seguir estão os métodos definidos por esta interface:

  • public String getName(): retorna o nome de identificação da conquista.
  • public void addAchievement(Object user, Achievement achievement): usado para atribuir um usuário a uma conquista, tando no caso de inserção como no caso de upgrade.
  • public void removeAchievement(Object user, Achievement achievement): usado para remover uma conquista de um determinado usuário. Dependendo do tipo de conquista, a operação pode ser efetuada uma supressão ou de atualização.

Gerenciamento de conquistas

Além da interface Achievement e suas implementações, o framework define um componente cuja função é armazenar as conquistas. A classe abstrata Game encapsula a mecânica gamification de armazenamento. Ele define métodos abstratos que devem ser implementados a fim de dar as ações apropriadas para atribuir ou remover conquistas do usuário. Atualmente, quatro subclasses de jogo estão disponíveis: GameMemoryStorage, que mantém dados armazenados apenas na memória; GameFileStorage, que armazena os resultados em um arquivo de propriedades; GameDatabaseStorage, que salva os affordances em um banco de dados SQL; e GameMongoStorage, que salva os dados em um banco de dados não relacional.

Os métodos relativos à armazenagem de conquistas são:

  • public abstract void insertAchievement (Object user, Achievement achievement): define o que deve ser feito para atribuir uma nova conquista para um usuário.
  • public abstract void deleteAchievement (Object user, Achievement achievement): define o que deve ser feito para eliminar uma conquista de um usuário.
  • public abstract void updateAchievement (Object user, Achievement achievement): define o que deve ser feito para mudar uma conquista que o usuário possui.
  • public abstract Achievement getAchievement (Object user, String achievementName): define a forma de recuperar dados de conquista de um usuário.
  • public abstract Map <String, Achievement> getAchievements (Object user): configura como recuperar todas as conquistas de um usuário.
  • public abstract Map <String, Achievement> getAllAchievements(Class achievementType): configura como recuperar todas as conquistas de um tipo.

As subclasses concretas do jogo devem gerenciar as conquistas sem o uso de seus tipos concretos. Isto é importante para permitir a extensão dos tipos de conquista.

As implementações da classe Game podem fornecer métodos mais específicos para consultar as informações gamification. Por exemplo, pode haver métodos para recuperar as classificações ou para localizar a posição do usuário. Em versões futuras esses recursos devem ser padronizados na API do framework.

Metadados gamification

Além da criação e armazenamento de conquistas, as operações que adicionam ou removem as conquistas podem ser configuradas através de anotações para serem acionadas com base na invocação de métodos de interface do aplicativo. A lista de anotações fornecidos pelo framework Esfinge Gamification para a configuração das conquistas é descrita abaixo.


Anotações Descrição geral
@PointsToUser, @RankingsToUser,
@RewardsToUser, @TrophiesToUses
Estas anotações permitem o incremento de uma implementação de conquistas para o usuário atual.
@RemoveRankings, @RemovePoints,
@RemoveReward, @RemoveTrophy
Estas anotações permitem a eliminação de uma implementação de conquistas de um determinado usuário.
@PointToParam
Esta anotação permite o incremento de Pontos para outro usuário, ou seja, a ação do usuário logado no sistema gera pontos para outro usuário.
@AllowPointGreaterThan, @AllowPointLessOrEqualsThan,
@DenyPointGreaterThan, @DenyPointLessOrEqualsThan
Estas anotações verificam se os pontos respeitam as restrições de maior ou menor igual a uma determinada quantidade de pontos definida na anotação para que a autorização seja permitida ou não.
@AllowTrophy, @DenyTrophy Estas anotações verificam o acesso de usuários a recursos protegidos com a restrição de troféu, isto é, quando algum usuário possuir o troféu conseguirá ou não acessar o recurso.
@AllowReward, @DenyReward Estas anotações verificam o acesso de usuários a recursos protegidos com a restrição de recompensa, isto é, quando algum usuário possuir o recompensa conseguirá ou não acessar o recurso.
@AllowRanking, @AllowLevel, @AllowRankingAndLevel, @AllowRankingOrLevel,
@DenyLevel, @DenyRanking, @DenyRankingAndLevel, @DenyRankingOrLevel
As anotações de ranking possuem a mesma lógica das anteriores, porém, visando os recursos do ranking, permitindo e não permitindo o acesso a recursos com as restrições de ranking e level.

É importante ressaltar que a anotação @PointsToParam pode fazer uso da anotação @Named para rotular o parâmetro que contém o ID do usuário que deve receber os pontos. Abaixo, exemplifica-se como estas anotações devem ser configuradas em uma interface do aplicativo.

public interface ITestAnnotations {
@PointsToUser(name = "GOLD", quantity = 1000)
public void doSomething();
@RewardsToUser(Name = "lunch", used = false)
public void doSomethingRemarcable();
@RemovePoints(name = "GOLD", quantity = 500)
public void doBadThing();
@RemoveReward(Name = "lunch", used = true)
public void useReward();
@PointsToParam (name = "SILVER", quantity = 100, param = "owner")
public void niceComment(String comment, @Named("owner") String owner);
@PointsToParam (name = "SILVER", quantity = 300, param = "comment"
prop ="user.login")
public void niceComment(@Named("comment") Comment c); }
Nos dois primeiros métodos há um exemplo de anotações que dão conquistas para o usuário atual, e nos próximos dois há exemplos de anotações para desencadear a remoção deles. Os últimos dois métodos apresentam exemplos de uma anotação que dá pontos para um usuário que está sendo referenciado em um param. O atributo da anotação param refere-se ao nome de atributo, marcado pela anotação @Named, que contém o ID de usuário. O atributo prop pode ser utilizado para configurar o estabelecimento de parâmetros que contém a informação.
É importante ressaltar que não houve uma preocupação em criar um grande número de anotações para cobrir todos os requisitos possíveis. No entanto, em vez do framework, existe um mecanismo que será apresentado na próxima subseção que permite a extensão das suas anotações. As anotações fornecidas pretendem exemplificar que tipo de configurações que pode ser realizada.

Pontos de extensão

O framework Esfinge Gamification tem dois pontos de extensão internos: um que configura a persistência e outro que permite a adição de novos tipos de conquistas. A persistência pode ser estendida para ser compatível com o que é usado na aplicação. Este ponto de extensão pode ser ampliado através da criação de uma nova subclasse da classe abstrata Game e configurado na classe GameInvoker. Para criar novos tipos de conquistas, o primeiro passo é criar uma nova implementação da interface Achievement, que define as regras para a adição e remoção de tais conquistas. O mecanismo de persistência deve também estar pronto para lidar com essas conquistas e devem ser criadas anotações para desencadear ações para a sua gestão. Alguns detalhes para esses pontos de extensão foram apresentadas nas seções anteriores.

A criação de novas anotações pode ser visto como o ponto de extensão principal. Para cada nova anotação deve existir uma classe que sabe como interpretar as informações e executar a ação que deve ser acionada quando um método com ela é invocado. No caso de anotações de segurança, para criação de novas autorizações, a última seção do framework Esfinge Guardian, Estendendo o Framework possui as orientações para realizar a criação de novos componentes. O código a seguir apresenta a anotação @PointsToUser para ilustrar como esta extensão funciona. Todas as anotações gamification devem possuir uma anotação @GamificationProcessor que configura a classe do processador relacionado.

      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.METHOD)
      @GamificationProcessor(PointsToUserProcessor.class)

      public @interface PointsToUser {
        int quantity();
        String name();
      }

A classe configurada na anotação deve implementar a interface AchievementProcessor. Essa interface define o método receiveAnnotation(), que é responsável por interpretar a anotação, recuperando informações de seus atributos específicos. O método process()é responsável por executar a ação na lógica gamification relacionada com a anotação. Nesta classe específica que dá pontos para o usuário atual.

public class PointsToUserProcessor implements AchievementProcessor {
        private int quantity;
        private String name;

        @Override
        public void receiveAnnotation(Annotation an) {
        PointsToUser ptu = (PointsToUser) an;
        quantity = ptu.quantity();
        name = ptu.name();
      }

      @Override
      public void process(Game game, Object encapsulated, Method method,
            Object[] args) {
          Object currentUser = UserStorage.getUserID();
          Point p = new Point(quantity, name);
          game.addAchievement(currentUser, p);
        }
      }

É importante destacar que este mecanismo pode ser usado para adicionar lógica específica do aplicativo diferente para o framework. Por exemplo, uma anotação pode configurar pontos para o usuário atual, a alguém relacionado com a ação do usuário, e até mesmo para grupo ou uma equipe em que o usuário participa. No entanto, usando esta abordagem, as ações relacionadas com o gamification são dissociados das classes de aplicação, estando relacionadas apenas por seus metadados.

 

 

 

Apoio

Todos os direitos reservados