private string?MapPoint(TokenTextPoint point, TiledTextPart part) { int rowIndex = point.Y - 1; int tileIndex = point.X - 1; if (rowIndex >= part.Rows.Count) { Logger?.LogError($"Location point {point} out of part's rows"); return(null); } if (tileIndex >= part.Rows[rowIndex].Tiles.Count) { Logger?.LogError($"Location point {point} out of part's row tiles"); return(null); } if (!part.Rows[rowIndex].Tiles[tileIndex].Data.ContainsKey("id")) { Logger?.LogError($"Location point {point} maps to tile without id"); return(null); } return(part.Rows[rowIndex].Tiles[tileIndex].Data["id"]); }
private static TiledTextPart GetTiledTextPart(int rowCount) { TiledTextPart part = new TiledTextPart { ItemId = Guid.NewGuid().ToString(), CreatorId = "zeus", UserId = "zeus" }; char c = 'a'; for (int y = 0; y < rowCount; y++) { TextTileRow row = new TextTileRow { Y = y + 1 }; part.Rows.Add(row); for (int x = 0; x < 3; x++) { TextTile tile = new TextTile { X = x + 1, }; tile.Data[TextTileRow.TEXT_DATA_NAME] = $"{c}{x + 1}"; row.Tiles.Add(tile); if (++c > 'z') { c = 'a'; } } } return(part); }
/// <summary> /// Pick (if possible) the specified count of random locations in the /// base text part, each with its corresponding piece of text. /// </summary> /// <param name="part">The part.</param> /// <param name="count">The count.</param> /// <returns>A list of tuples where 1=location, 2=base text.</returns> private IList <Tuple <string, string> > PickLocAndTexts( TiledTextPart part, int count) { HashSet <Tuple <int, int> > usedCoords = new HashSet <Tuple <int, int> >(); List <Tuple <string, string> > results = new List <Tuple <string, string> >(); while (count > 0) { for (int attempt = 0; attempt < 10; attempt++) { // pick a row int y = Randomizer.Seed.Next(1, part.Rows.Count + 1); // pick a tile in that line int x = Randomizer.Seed.Next(1, part.Rows[y - 1].Tiles.Count + 1); // select if not already used Tuple <int, int> yx = Tuple.Create(y, x); if (!usedCoords.Contains(yx)) { usedCoords.Add(yx); results.Add(Tuple.Create($"{y}.{x}", part.Rows[y - 1].Tiles[x - 1] .Data[TextTileRow.TEXT_DATA_NAME])); break; } } count--; } return(results); }
public void GetDataPins_NoCitation_Empty() { TiledTextPart part = GetPart(); part.Citation = null; Assert.Empty(part.GetDataPins()); }
public void GetTextAt_3LinesRange_Ok(string location, string expectedText) { TiledTextPart textPart = GetTiledTextPart(3); TiledTextLayerPart <CommentLayerFragment> layerPart = GetPart(); string text = layerPart.GetTextAt(textPart, location); Assert.Equal(expectedText, text); }
public void GetTextAt_InvalidLocation_Null() { TiledTextPart textPart = GetTiledTextPart(3); TiledTextLayerPart <CommentLayerFragment> layerPart = GetPart(); string text = layerPart.GetTextAt(textPart, "12.3"); Assert.Null(text); }
public void GetDataPins_Citation_1() { TiledTextPart part = GetPart(); List <DataPin> pins = part.GetDataPins().ToList(); Assert.Single(pins); DataPin pin = pins[0]; Assert.Equal(part.ItemId, pin.ItemId); Assert.Equal(part.Id, pin.PartId); Assert.Equal(part.RoleId, pin.RoleId); Assert.Equal("citation", pin.Name); Assert.Equal("some-citation", pin.Value); }
private static string GetPartTextDescription(TiledTextPart part) { StringBuilder sb = new(); // collect head text int ya = 0, xa = 0; foreach (TextTileRow row in part.Rows) { ya++; xa = 0; foreach (TextTile tile in row.Tiles) { xa++; if (sb.Length > 0) { sb.Append(' '); } sb.Append(tile.Data[KEY_TEXT]); if (sb.Length >= 40) { goto tail; } } } tail: // collect tail text int i = sb.Length; for (int yb = part.Rows.Count; yb >= ya; yb--) { for (int xb = part.Rows[yb - 1].Tiles.Count; yb == ya? xb > xa : xb > 0; xb--) { sb.Insert(i, part.Rows[yb - 1].Tiles[xb - 1].Data[KEY_TEXT]); sb.Insert(i, ' '); if (sb.Length - i >= 40) { sb.Insert(i, "... "); goto end; } } } end: return(sb.ToString()); }
public void Seed_Options_Tag() { TiledTextPartSeeder seeder = new TiledTextPartSeeder(); seeder.SetSeedOptions(_seedOptions); IPart part = seeder.GetPart(_item, null, _factory); Assert.NotNull(part); TiledTextPart tp = part as TiledTextPart; Assert.NotNull(tp); TestHelper.AssertPartMetadata(tp); Assert.NotNull(tp.Citation); Assert.NotEmpty(tp.Rows); for (int y = 1; y <= tp.Rows.Count; y++) { Assert.Equal(y, tp.Rows[y - 1].Y); } }
public void Part_Is_Serializable() { TiledTextPart part = GetPart(); string json = TestHelper.SerializePart(part); TiledTextPart part2 = TestHelper.DeserializePart <TiledTextPart>(json); Assert.Equal(part.Id, part2.Id); Assert.Equal(part.TypeId, part2.TypeId); Assert.Equal(part.ItemId, part2.ItemId); Assert.Equal(part.RoleId, part2.RoleId); Assert.Equal(part.CreatorId, part2.CreatorId); Assert.Equal(part.UserId, part2.UserId); List <TextTileRow> expectedRows = GetRows(3); Assert.Equal(expectedRows.Count, part.Rows.Count); for (int i = 0; i < expectedRows.Count; i++) { Assert.Equal(expectedRows[i].Y, part.Rows[i].Y); Assert.Equal(expectedRows[i].Tiles.Count, part.Rows[i].Tiles.Count); Assert.Equal(expectedRows[i].Data.Count, part.Rows[i].Data.Count); } }
/// <summary> /// Creates and seeds a new part with its fragments. The fragment /// type comes from the part's role ID. /// </summary> /// <param name="item">The item this part should belong to.</param> /// <param name="roleId">The optional part role ID.</param> /// <param name="factory">The part seeder factory. This is used /// for layer parts, which need to seed a set of fragments.</param> /// <returns>A new part.</returns> /// <exception cref="ArgumentNullException">item or factory</exception> public override IPart GetPart(IItem item, string roleId, PartSeederFactory factory) { if (item == null) { throw new ArgumentNullException(nameof(item)); } if (factory == null) { throw new ArgumentNullException(nameof(factory)); } if (_options == null || _options.MaxFragmentCount < 1) { return(null); } // get the base text part; nothing to do if none TiledTextPart textPart = item.Parts .OfType <TiledTextPart>() .FirstOrDefault(); if (textPart == null) { return(null); } // get the seeder; nothing to do if none string frTypeId = StripColonSuffix(roleId); IFragmentSeeder seeder = factory.GetFragmentSeeder("seed." + frTypeId); if (seeder == null) { return(null); } // get the layer part for the specified fragment type Type constructedType = typeof(TiledTextLayerPart <>) .MakeGenericType(seeder.GetFragmentType()); IPart part = (IPart)Activator.CreateInstance(constructedType); // seed metadata SetPartMetadata(part, frTypeId, item); // seed by adding fragments int count = Randomizer.Seed.Next(1, _options.MaxFragmentCount); IList <Tuple <string, string> > locAndTexts = PickLocAndTexts(textPart, count); // must invoke AddFragment via reflection, as the closed type // is known only at runtime Type t = part.GetType(); foreach (var lt in locAndTexts) { ITextLayerFragment fr = seeder.GetFragment( item, lt.Item1, lt.Item2); if (fr != null) { t.InvokeMember("AddFragment", BindingFlags.InvokeMethod, null, part, new[] { fr }); } } return(part); }
/// <summary> /// Creates and seeds a new part. /// </summary> /// <param name="item">The item this part should belong to.</param> /// <param name="roleId">The optional part role ID.</param> /// <param name="factory">The part seeder factory. This is used /// for layer parts, which need to seed a set of fragments.</param> /// <returns>A new part.</returns> /// <exception cref="ArgumentNullException">item or factory</exception> public override IPart GetPart(IItem item, string roleId, PartSeederFactory factory) { if (item == null) { throw new ArgumentNullException(nameof(item)); } if (factory == null) { throw new ArgumentNullException(nameof(factory)); } TiledTextPart part = new TiledTextPart(); SetPartMetadata(part, roleId, item); // citation part.Citation = Randomizer.Seed.Next(1, 100) .ToString(CultureInfo.InvariantCulture); // from 2 to 10 rows var faker = new Faker(); string text = faker.Lorem.Sentences( Randomizer.Seed.Next(2, 11)); int y = 1; foreach (string line in text.Split('\n')) { // row TextTileRow row = new TextTileRow { Y = y++, }; // row's data for (int i = 0; i < Randomizer.Seed.Next(0, 4); i++) { row.Data[$"d{(char)(i + 97)}"] = faker.Lorem.Word(); } // add tiles in row int x = 1; foreach (string token in line.Trim().Split(' ')) { TextTile tile = new TextTile { X = x++, }; // text tile.Data[TextTileRow.TEXT_DATA_NAME] = token; // other data for (int i = 0; i < Randomizer.Seed.Next(0, 11); i++) { tile.Data[$"d{(char)(i + 97)}"] = faker.Lorem.Word(); } row.Tiles.Add(tile); } part.Rows.Add(row); } return(part); }
/// <summary> /// Imports the partition into a Cadmus item. /// </summary> /// <param name="div">The document's div element containing the partition, /// or a part of it.</param> /// <param name="rowElements">The rows elements, i.e. the children elements /// of the partition representing tiled text rows (either <c>l</c> or /// <c>p</c> elements).</param> /// <returns>The item.</returns> private IItem ImportPartition(XElement div, IList <XElement> rowElements) { _partitionNr++; // build citation string cit = XmlHelper.GetBreakPointCitation(_partitionNr, div.Elements().FirstOrDefault(IsLOrP), _docId); // item var nBounds = GetPartitionNBoundaries(rowElements); Item item = new Item { Title = cit, //Description = (nBounds != null ? // $"{nBounds.Item1}-{nBounds.Item2} " : "") + // GetDescriptionText(div.Value.Trim()), FacetId = _facetId, GroupId = _docId, CreatorId = _userId, UserId = UserId }; // text part TiledTextPart part = new TiledTextPart { ItemId = item.Id, Citation = cit, CreatorId = item.CreatorId, UserId = item.UserId, RoleId = PartBase.BASE_TEXT_ROLE_ID }; item.Parts.Add(part); int y = 1; int wordNr = 1; foreach (XElement rowElement in rowElements) { // row TextTileRow row = new TextTileRow { Y = y++ }; row.Data["_name"] = rowElement.Name.LocalName; // row's attributes foreach (XAttribute attr in rowElement.Attributes()) { string key = GetKeyFromAttrName(attr.Name); row.Data[key] = attr.Value; } // tiles if (rowElement.Elements(XmlHelper.TEI + "w").Any()) { AddTiles(rowElement.Elements(XmlHelper.TEI + "w"), row); } else { int divNr = div.ElementsBeforeSelf(div.Name).Count() + 1; row.Data["_split"] = "1"; var wordAndIds = from w in rowElement.Value.Split(' ') select Tuple.Create( w, $"d{divNr:000}w{wordNr++}"); AddTiles(wordAndIds, row); } part.Rows.Add(row); } item.Description = (nBounds != null ? $"{nBounds.Item1}-{nBounds.Item2} " : "") + GetPartTextDescription(part); item.SortKey = _sortKeyBuilder.BuildKey(item, null); int i = item.SortKey.IndexOf(' ', item.SortKey.IndexOf(' ') + 1); item.SortKey = item.SortKey.Substring(0, i); return(item); }