You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
3.1 KiB
C
133 lines
3.1 KiB
C
#include "poll.h"
|
|
|
|
#include "model/account.h"
|
|
#include "model/emoji.h"
|
|
#include "model/status.h"
|
|
|
|
#include "collections/array.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
|
|
#define OBJ_TYPE struct status_poll_option
|
|
struct json_object_field status_poll_option_layout[] = {
|
|
JSON_FIELD_STRING( title, true ),
|
|
JSON_FIELD_ARRAY_OF_INTS( votes, false ),
|
|
JSON_FIELD_END,
|
|
};
|
|
#undef OBJ_TYPE
|
|
JSON_FIELD_TYPE_OBJECT_LAYOUT_WITH_DEFAULTS( status_poll_option );
|
|
|
|
#define OBJ_TYPE struct status_poll
|
|
struct json_object_field status_poll_layout[] = {
|
|
JSON_FIELD_INTEGER( id, false ),
|
|
JSON_FIELD_INTEGER( votes_count, false ),
|
|
JSON_FIELD_ARRAY_OF_INTS( own_votes, false ),
|
|
JSON_FIELD_BOOL( multiple_choice, false ),
|
|
JSON_FIELD_DATETIME( expires_at, false ),
|
|
JSON_FIELD_BOOL( voted, false ),
|
|
JSON_FIELD_ARRAY_OF_TYPE( options, false, status_poll_option_type ),
|
|
JSON_FIELD_ARRAY_OF_TYPE( emoji, false, emoji_type ),
|
|
JSON_FIELD_END,
|
|
};
|
|
#undef OBJ_TYPE
|
|
JSON_FIELD_TYPE_OBJECT_LAYOUT_WITH_DEFAULTS( status_poll );
|
|
|
|
void status_poll_option_free( struct status_poll_option* o )
|
|
{
|
|
if( !o ) { return; }
|
|
|
|
free(o);
|
|
}
|
|
void status_poll_free( struct status_poll* p )
|
|
{
|
|
if( !p ) { return; }
|
|
|
|
for( int i = 0; i < p->options.count; ++i ) {
|
|
status_poll_option_free( p->options.items[i] );
|
|
}
|
|
free( p->options.items );
|
|
|
|
for( int i = 0; i < p->emoji.count; ++i ) {
|
|
emoji_free( p->emoji.items[i] );
|
|
}
|
|
free( p->emoji.items );
|
|
|
|
free(p->own_votes.items);
|
|
|
|
free(p);
|
|
}
|
|
bool status_poll_has_option( struct status_poll* p, int idx )
|
|
{
|
|
if( idx < 0 ) { return false; }
|
|
return idx < p->options.count;
|
|
}
|
|
bool status_poll_add_vote( struct status* s, struct account* a, void* choices_ptr )
|
|
{
|
|
// Verify preconditions
|
|
if( !s ) { return false; }
|
|
if( !a ) { return false; }
|
|
if( !choices_ptr ) { return false; }
|
|
|
|
struct {
|
|
int* items;
|
|
int count;
|
|
} *choices = choices_ptr;
|
|
|
|
// Validate vote choices
|
|
for( int i = 0; i < choices->count; ++i ) {
|
|
if( !status_poll_has_option( s->poll, choices->items[i] ) ) {
|
|
printf( "Poll doesn't have option %d\n", choices->items[i] );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Update model
|
|
for( int i = 0; i < choices->count; ++i ) {
|
|
int choice = choices->items[i];
|
|
struct status_poll_option* option = s->poll->options.items[choice];
|
|
|
|
int id = a->id;
|
|
bool should_add = true;
|
|
if( id != poll_vote_unknown_id ) {
|
|
for( int j = 0; j < option->votes.count; ++j ) {
|
|
if( option->votes.items[j] == id ) {
|
|
should_add = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if( should_add ) {
|
|
array_append( &option->votes, sizeof(id), &id );
|
|
if( a->id == owner_account_id ) {
|
|
array_append( &s->poll->own_votes, sizeof(choice), &choice );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Federate response if account is owner
|
|
if( a->id == owner_account_id ) {
|
|
s->poll->voted = true;
|
|
|
|
// https://www.w3.org/TR/activitystreams-vocabulary/#questions
|
|
// See Example 153
|
|
|
|
// TODO: Create federation object
|
|
//struct ap_object* obj;
|
|
}
|
|
|
|
status_poll_update_vote_count( s->poll );
|
|
|
|
return true;
|
|
}
|
|
|
|
void status_poll_update_vote_count( struct status_poll* poll )
|
|
{
|
|
poll->votes_count = 0;
|
|
for( int i = 0; i < poll->options.count; ++i ) {
|
|
poll->votes_count += poll->options.items[i]->votes.count;
|
|
}
|
|
}
|
|
|