Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 440997e0

Přidáno uživatelem Vojtěch Bartička před téměř 3 roky(ů)

Tag merging for final annotation beta

Zobrazit rozdíly:

Backend/Backend/Controllers/DocumentController.cs
2 2
using Microsoft.AspNetCore.Mvc;
3 3
using RestAPI.Utils;
4 4
using System.Net;
5
using Serilog;
6 5
using ILogger = Serilog.ILogger;
7 6
using Models.Documents;
8 7
using RestAPI.Exceptions;
9 8
using RestAPI.Authentication;
9
using Models.Annotations;
10
using Core.Services.AnnotationService;
10 11

  
11 12
namespace RestAPI.Controllers;
12 13

  
......
16 17
{
17 18
    private readonly IDocumentService documentService;
18 19
    private readonly ILogger logger;
20
    private readonly IAnnotationService annotationService;
19 21

  
20

  
21
    public DocumentController(IDocumentService documentService, ILogger logger)
22
    public DocumentController(IDocumentService documentService, IAnnotationService annotationService, ILogger logger)
22 23
    {
23 24
        this.documentService = documentService;
24 25
        this.logger = logger;
26
        this.annotationService = annotationService;
25 27
    }
26 28

  
27 29
    [HttpGet("/documents")]
......
180 182
        }
181 183
    }
182 184

  
185
    [HttpPost("/document/{documentId}/final")]
186
    [Authorize(Models.Enums.ERole.ADMINISTRATOR)]
187
    [ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(CreateFinalAnnotationResponse))]
188
    [ProducesResponseType((int)HttpStatusCode.Forbidden)]
189
    public ActionResult<CreateFinalAnnotationResponse> CreateFinalAnnotation([FromServices] ClientInfo clientInfo, Guid documentId)
190
    {
191
        if (clientInfo.LoggedUser == null)
192
        {
193
            logger.Warning("ClientInfo has null LoggerUser in [Authorized] controller");
194
            return Problem();
195
        }
196

  
197
        try
198
        {
199
            var guid = annotationService.CreateFinalAnnotation(documentId, clientInfo.LoggedUser.Id);
200

  
201
            return Ok(new CreateFinalAnnotationResponse()
202
            {
203
                FinalAnnotationId = guid
204
            });
205
        }
206
        catch (InvalidOperationException e)
207
        {
208
            throw new BadRequestException(e.Message);
209
        }
210
    }
183 211
}
184 212

  
Backend/Backend/appsettings.Development.json
6 6
    }
7 7
  },
8 8
  "AllowedHosts": "*",
9
  "ConnectionString": "Host=localhost:5432;Database=dbo;Username=myuser;Password=password",  
9
  "ConnectionString": "Host=localhost:5432;Database=dbo;Username=myuser;Password=password;Include Error Detail=true;",  
10 10
  "JwtConfig": {
11 11
    "Secret": "CJgvc9BtwJjnCExzKLB2ndtxERW3YMhqMMPNrBZuTJaskPqRVfZQHRUnbRHH9Ekp5zsaTSeM73vQSKvq48w2u8jTnKUn7Uhk2zBeD9wLz48ssKMppNC9HDTXSk6RWP5PtXfCayJ67mbUWF6aknnteLg4sDKzqYeNYjyw8Jk6",
12 12
    "Issuer": "0x00.server"
Backend/Core/MapperProfiles/TagProfileEF.cs
18 18
            CreateMap<SubTag, SubTagInfo>();
19 19
            CreateMap<AnnotationTag, TagInstanceInfo>()
20 20
                .ForMember(ti => ti.OccurenceId, opt => opt.MapFrom(at => at.Id));
21

  
22
            // Ignore ID and Annotation
23
            CreateMap<AnnotationTag, FinalAnnotationTag>()
24
                .ForMember(fat => fat.Id, opt => opt.Ignore())
25
                .ForMember(fat => fat.Annotation, opt => opt.Ignore());
21 26
        }
22 27
    }
23 28
}
Backend/Core/Services/AnnotationService/AnnotationServiceEF.cs
258 258
                    for (; i < descCount; i++)
259 259
                    {
260 260
                        var node = descendantsToEdit.ElementAt(i);
261
                        if (!node.Name.Contains("#text") || addedForSelection.Contains(node) || addedForSelection.Contains(node.ParentNode) ||
262
                            node.ParentNode.Name == "style")
261
                        if (!node.Name.Contains("#text") || addedForSelection.Contains(node) || addedForSelection.Contains(node.ParentNode) || node.ParentNode.Name == "style")
263 262
                        {
264 263
                            continue;
265 264
                        }
......
959 958
            annotation.State = done ? EState.DONE : EState.IN_PROGRESS;
960 959
            context.SaveChanges();
961 960
        }
961

  
962
        public Guid CreateFinalAnnotation(Guid documentId, Guid userId)
963
        {
964
            var document = context.Documents.Single(d => d.Id == documentId);
965
            var user = context.Users.Single(u => u.Id == userId);
966

  
967
            // Remove existing 
968
            if (context.FinalAnnotations.Any(fa => fa.Document == document))
969
            {
970
                var finalAnnotationOld = context.FinalAnnotations.Single(fa => fa.Document == document);
971
                context.FinalAnnotations.Remove(finalAnnotationOld);
972
            }
973

  
974
            var annotations = context.Annotations
975
                .Include(a => a.Document)
976
                .Where(a => a.Document == document && a.State == EState.DONE)
977
                .ToList();
978

  
979
            var finalAnnotation = new FinalAnnotation()
980
            {
981
                Id = Guid.NewGuid(),
982
                DateAssigned = DateTime.Now,
983
                DateLastChanged = DateTime.Now,
984
                Document = document,
985
                User = user,
986
                UserAssigned = user,
987
                Annotations = annotations,
988
                State = EState.NEW
989
            };
990

  
991
            List<AnnotationTag> annotationTagsAll = new();
992
            foreach (var annotation in annotations)
993
            {
994
                annotationTagsAll.AddRange(context.AnnotationTags
995
                    .Where(at => at.Annotation == annotation)
996
                    .Include(at => at.Tag)
997
                    .Include(at => at.SubTag)
998
                    .Include(at => at.Annotation)
999
                    .ThenInclude(a => a.User)
1000
                    .ToList());
1001
            }
1002
            annotationTagsAll = annotationTagsAll.OrderBy(at => at.Position).ToList();
1003

  
1004
            Dictionary<Guid, List<AnnotationTag>> occurenceDict = new();
1005
            foreach (var annotationTag in annotationTagsAll)
1006
            {
1007
                if (occurenceDict.ContainsKey(annotationTag.Instance))
1008
                {
1009
                    occurenceDict[annotationTag.Instance].Add(annotationTag);
1010
                }
1011
                else
1012
                {
1013
                    occurenceDict[annotationTag.Instance] = new();
1014
                    occurenceDict[annotationTag.Instance].Add(annotationTag);
1015
                }
1016
            }
1017

  
1018
            List<List<AnnotationTag>> occurenceLists = new();
1019
            foreach (var key in occurenceDict.Keys)
1020
            {
1021
                occurenceLists.Add(occurenceDict[key]);
1022
            }
1023

  
1024
            List<List<AnnotationTag>> annotationTagsProcessed = new();
1025
            List<FinalAnnotationTag> finalAnnotationTags = new();
1026
            for (int i = 0; i < occurenceLists.Count; i++)
1027
            {
1028
                var occurrenceList1 = occurenceLists[i];
1029
                List<List<AnnotationTag>> sameLists = new();
1030

  
1031
                for (int j = 0; j < occurenceLists.Count; j++)
1032
                {
1033
                    var occurrenceList2 = occurenceLists[j];
1034

  
1035
                    if (annotationTagsProcessed.Contains(occurrenceList2))
1036
                    {
1037
                        continue;
1038
                    }
1039

  
1040
                    if (SelectionsAreSame(occurrenceList1, occurrenceList2))
1041
                    {
1042
                        sameLists.Add(occurrenceList2);
1043
                    }
1044
                }
1045

  
1046
                // This means that this occurrence ahs already been processed as matching a previous tag
1047
                if (sameLists.Count() == 0)
1048
                {
1049
                    continue;
1050
                }
1051

  
1052
                List<User> relatedUsers = new();
1053
                foreach (var list in sameLists)
1054
                {
1055
                    relatedUsers.Add(list[0].Annotation.User);
1056
                }
1057

  
1058
                foreach (var tag in sameLists[0])
1059
                {
1060
                    finalAnnotationTags.Add(new()
1061
                    {
1062
                        Id = Guid.NewGuid(),
1063
                        Tag = tag.Tag,
1064
                        SubTag = tag.SubTag,
1065
                        Annotation = finalAnnotation,
1066
                        SelectedText = tag.SelectedText,
1067
                        Sentiment = tag.Sentiment,
1068
                        Instance = tag.Instance,
1069
                        IsFinal = sameLists.Count == annotations.Count,
1070
                        Length = tag.Length,
1071
                        Position = tag.Position,
1072
                        Note = "",
1073
                        Users = relatedUsers
1074
                    });
1075
                }
1076

  
1077
                annotationTagsProcessed.AddRange(sameLists);
1078
            }
1079

  
1080
            context.FinalAnnotations.Add(finalAnnotation);
1081
            context.SaveChanges();
1082
            context.FinalAnnotationTags.AddRange(finalAnnotationTags);
1083

  
1084
            context.SaveChanges();
1085
            return finalAnnotation.Id;
1086
        }
1087

  
1088
        private bool SelectionsAreSame(List<AnnotationTag> list1, List<AnnotationTag> list2)
1089
        {
1090
            if (list1.Count != list2.Count)
1091
            {
1092
                return false;
1093
            }
1094

  
1095
            bool sentimentEnabled = list1[0].Tag.SentimentEnabled;
1096

  
1097
            if (sentimentEnabled)
1098
            {
1099
                for (int i = 0; i < list1.Count; i++)
1100
                {
1101
                    var tag1 = list1[i];
1102
                    var tag2 = list2[i];
1103
                    if (tag1.Position == tag2.Position &&
1104
                        tag1.Length == tag2.Length &&
1105
                        tag1.Sentiment == tag2.Sentiment &&
1106
                        tag1.Tag == tag2.Tag &&
1107
                        tag1.SubTag == tag2.SubTag)
1108
                    {
1109
                        continue;
1110
                    }
1111
                    else
1112
                    {
1113
                        return false;
1114
                    }
1115
                }
1116
            }
1117
            else
1118
            {
1119
                for (int i = 0; i < list1.Count; i++)
1120
                {
1121
                    var tag1 = list1[i];
1122
                    var tag2 = list2[i];
1123
                    if (tag1.Position == tag2.Position &&
1124
                        tag1.Length == tag2.Length &&
1125
                        tag1.Tag == tag2.Tag &&
1126
                        tag1.SubTag == tag2.SubTag)
1127
                    {
1128
                        continue;
1129
                    }
1130
                    else
1131
                    {
1132
                        return false;
1133
                    }
1134
                }
1135
            }
1136

  
1137
            return true;
1138
        }
962 1139
    }
963 1140
}
Backend/Core/Services/AnnotationService/IAnnotationService.cs
18 18
        public void AddNoteToAnnotation(Guid annotationId, Guid userId, ERole userRole, AddNoteToAnnotationRequest request);
19 19
        public void SetTagInstanceSentiment(Guid annotationId, Guid instanceId, Guid userId, ERole userRole, ETagSentiment sentiment);
20 20
        public void MarkAnnotationAsDone(Guid annotationId, Guid userId, ERole userRole, bool done);
21
        public Guid CreateFinalAnnotation(Guid documentId, Guid userId);
21 22
    }
22 23
}
Backend/Models/Annotations/CreateFinalAnnotationResponse.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6

  
7
namespace Models.Annotations
8
{
9
    public class CreateFinalAnnotationResponse
10
    {
11
        public Guid FinalAnnotationId { get; set; }
12
    }
13
}

Také k dispozici: Unified diff