using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Text.Json; using System.Text.Json.Serialization; using DysonNetwork.Shared.Proto; using Google.Protobuf.WellKnownTypes; using NodaTime; namespace DysonNetwork.Shared.Models; public class SnPoll : ModelBase { public Guid Id { get; set; } = Guid.NewGuid(); public List Questions { get; set; } = new(); [MaxLength(1024)] public string? Title { get; set; } [MaxLength(4096)] public string? Description { get; set; } public Instant? EndedAt { get; set; } public bool IsAnonymous { get; set; } public Guid PublisherId { get; set; } [JsonIgnore] public SnPublisher? Publisher { get; set; } public Poll ToProtoValue() { var proto = new Poll { Id = Id.ToString(), IsAnonymous = IsAnonymous, PublisherId = PublisherId.ToString(), Publisher = Publisher?.ToProtoValue(), CreatedAt = Timestamp.FromDateTimeOffset(CreatedAt.ToDateTimeOffset()), UpdatedAt = Timestamp.FromDateTimeOffset(UpdatedAt.ToDateTimeOffset()), }; if (Title != null) proto.Title = Title; if (Description != null) proto.Description = Description; if (EndedAt.HasValue) proto.EndedAt = Timestamp.FromDateTimeOffset(EndedAt.Value.ToDateTimeOffset()); proto.Questions.AddRange(Questions.Select(q => q.ToProtoValue())); if (DeletedAt.HasValue) proto.DeletedAt = Timestamp.FromDateTimeOffset(DeletedAt.Value.ToDateTimeOffset()); return proto; } public static SnPoll FromProtoValue(Poll proto) { var poll = new SnPoll { Id = Guid.Parse(proto.Id), Title = proto.Title != null ? proto.Title : null, Description = proto.Description != null ? proto.Description : null, IsAnonymous = proto.IsAnonymous, PublisherId = Guid.Parse(proto.PublisherId), Publisher = proto.Publisher != null ? SnPublisher.FromProtoValue(proto.Publisher) : null, CreatedAt = Instant.FromDateTimeOffset(proto.CreatedAt.ToDateTimeOffset()), UpdatedAt = Instant.FromDateTimeOffset(proto.UpdatedAt.ToDateTimeOffset()), }; if (proto.EndedAt != null) poll.EndedAt = Instant.FromDateTimeOffset(proto.EndedAt.ToDateTimeOffset()); poll.Questions.AddRange(proto.Questions.Select(SnPollQuestion.FromProtoValue)); if (proto.DeletedAt != null) poll.DeletedAt = Instant.FromDateTimeOffset(proto.DeletedAt.ToDateTimeOffset()); return poll; } } public enum PollQuestionType { SingleChoice, MultipleChoice, YesNo, Rating, FreeText } public class SnPollQuestion : ModelBase { public Guid Id { get; set; } = Guid.NewGuid(); public PollQuestionType Type { get; set; } [Column(TypeName = "jsonb")] public List? Options { get; set; } [MaxLength(1024)] public string Title { get; set; } = null!; [MaxLength(4096)] public string? Description { get; set; } public int Order { get; set; } = 0; public bool IsRequired { get; set; } public Guid PollId { get; set; } [JsonIgnore] public SnPoll Poll { get; set; } = null!; public PollQuestion ToProtoValue() { var proto = new PollQuestion { Id = Id.ToString(), Type = (Proto.PollQuestionType)((int)Type + 1), Title = Title, Order = Order, IsRequired = IsRequired, }; if (Description != null) proto.Description = Description; if (Options != null) proto.Options.AddRange(Options.Select(o => o.ToProtoValue())); return proto; } public static SnPollQuestion FromProtoValue(PollQuestion proto) { var question = new SnPollQuestion { Id = Guid.Parse(proto.Id), Type = (PollQuestionType)((int)proto.Type - 1), Title = proto.Title, Order = proto.Order, IsRequired = proto.IsRequired, }; if (proto.Description != null) question.Description = proto.Description; if (proto.Options.Count > 0) question.Options = proto.Options.Select(SnPollOption.FromProtoValue).ToList(); return question; } } public class SnPollOption { public Guid Id { get; set; } = Guid.NewGuid(); [Required][MaxLength(1024)] public string Label { get; set; } = null!; [MaxLength(4096)] public string? Description { get; set; } public int Order { get; set; } = 0; public PollOption ToProtoValue() { var proto = new PollOption { Id = Id.ToString(), Label = Label, Order = Order, }; if (Description != null) proto.Description = Description; return proto; } public static SnPollOption FromProtoValue(PollOption proto) { return new SnPollOption { Id = Guid.Parse(proto.Id), Label = proto.Label, Description = proto.Description != null ? proto.Description : null, Order = proto.Order, }; } } public class SnPollAnswer : ModelBase { public Guid Id { get; set; } = Guid.NewGuid(); [Column(TypeName = "jsonb")] public Dictionary Answer { get; set; } = null!; public Guid AccountId { get; set; } public Guid PollId { get; set; } [JsonIgnore] public SnPoll? Poll { get; set; } [NotMapped] public SnAccount? Account { get; set; } public PollAnswer ToProtoValue() { var proto = new PollAnswer { Id = Id.ToString(), Answer = GrpcTypeHelper.ConvertObjectToByteString(Answer), AccountId = AccountId.ToString(), PollId = PollId.ToString(), CreatedAt = Timestamp.FromDateTimeOffset(CreatedAt.ToDateTimeOffset()), UpdatedAt = Timestamp.FromDateTimeOffset(UpdatedAt.ToDateTimeOffset()), }; if (DeletedAt.HasValue) proto.DeletedAt = Timestamp.FromDateTimeOffset(DeletedAt.Value.ToDateTimeOffset()); return proto; } public static SnPollAnswer FromProtoValue(PollAnswer proto) { var answer = new SnPollAnswer { Id = Guid.Parse(proto.Id), Answer = GrpcTypeHelper.ConvertByteStringToObject>(proto.Answer), AccountId = Guid.Parse(proto.AccountId), PollId = Guid.Parse(proto.PollId), CreatedAt = Instant.FromDateTimeOffset(proto.CreatedAt.ToDateTimeOffset()), UpdatedAt = Instant.FromDateTimeOffset(proto.UpdatedAt.ToDateTimeOffset()), }; if (proto.DeletedAt != null) answer.DeletedAt = Instant.FromDateTimeOffset(proto.DeletedAt.ToDateTimeOffset()); return answer; } }