Пример #1
0
        /// <summary>
        /// Maps the specified location to 1 or 2 (for ranges) IDs.
        /// </summary>
        /// <param name="location">The location.</param>
        /// <param name="item">The parent item. The tiled text part will be
        /// searched among its parts.</param>
        /// <returns>Tuple where 1=first or single ID, 2=second ID or null
        /// when there is a single ID only; null if text part not found.</returns>
        /// <exception cref="ArgumentNullException">location or item</exception>
        public Tuple <string, string?>?Map(string location, IItem item)
        {
            if (location == null)
            {
                throw new ArgumentNullException(nameof(location));
            }
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            // find the tiled text part
            TiledTextPart?part =
                item.Parts.Find(p => p.TypeId == _tiledTextPartTypeId)
                as TiledTextPart;

            if (part == null)
            {
                Logger?.LogError($"No tiled text part for item {item}");
                return(null);
            }

            // parse and map location
            TokenTextLocation loc = TokenTextLocation.Parse(location);
            string?           a   = MapPoint(loc.A, part);

            if (a == null)
            {
                return(null);
            }

            if (loc.IsRange)
            {
                string?b = MapPoint(loc.B, part);
                if (b == null)
                {
                    return(null);
                }
                return(Tuple.Create(a !, (string?)b));
            }
            else
            {
                return(Tuple.Create(a, (string?)null));
            }
        }
Пример #2
0
        private static bool PartHasOverlaps(
            TiledTextLayerPart <ApparatusLayerFragment> part)
        {
            List <TokenTextLocation> locs = (from fr in part.Fragments
                                             select TokenTextLocation.Parse(fr.Location))
                                            .ToList();

            for (int i = 0; i < locs.Count; i++)
            {
                for (int j = i + 1; j < locs.Count; j++)
                {
                    if (locs[i].Overlaps(locs[j]))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
Пример #3
0
        private void AddFragmentToPart(ApparatusLayerFragment fr,
                                       TiledTextLayerPart <ApparatusLayerFragment> part,
                                       string originalLoc)
        {
            int count = part.Fragments.Count;

            // bypass part's add so that even overlapping fragments are added;
            // we will then move them all at once later, when splitting part
            TokenTextLocation loc = TokenTextLocation.Parse(fr.Location);

            if (part.Fragments.Any(f => TokenTextLocation.Parse(f.Location)
                                   .Overlaps(loc)))
            {
                Logger?.LogInformation(
                    $"Overlap for new fragment at {fr.Location}"
                    + $" (original {originalLoc}): "
                    + string.Join("; ", fr.Entries));
            }
            part.Fragments.Add(fr);
        }
        /// <summary>
        /// Gets the text at the specified location from the specified
        /// base text part.
        /// </summary>
        /// <param name="baseTextPart">The base text part to get text from.</param>
        /// <param name="location">The location.</param>
        /// <returns>The text, or null if location is invalid.</returns>
        /// <exception cref="ArgumentNullException">baseTextPart or location
        /// </exception>
        public override string GetTextAt(IPart baseTextPart, string location)
        {
            if (baseTextPart == null)
            {
                throw new ArgumentNullException(nameof(baseTextPart));
            }
            if (location == null)
            {
                throw new ArgumentNullException(nameof(location));
            }

            if (!(baseTextPart is TiledTextPart textPart))
            {
                return(null);
            }

            // parse
            TokenTextLocation loc = TokenTextLocation.Parse(location);
            int aRowIndex         = loc.A.Y - 1;

            if (aRowIndex < 0 || aRowIndex >= textPart.Rows.Count)
            {
                return(null);
            }
            List <TextTile> tiles;

            // range
            if (loc.IsRange)
            {
                // tokens range
                StringBuilder sb = new StringBuilder();

                int bRowIndex = loc.B.Y - 1;
                if (bRowIndex < aRowIndex || bRowIndex >= textPart.Rows.Count)
                {
                    return(null);
                }

                int aTileIndex = loc.A.X - 1;
                int bTileIndex = loc.B.X - 1;

                // corner case: same row for A-B
                if (aRowIndex == bRowIndex)
                {
                    // defensive
                    if (bTileIndex < aTileIndex)
                    {
                        return(null);
                    }
                    tiles = textPart.Rows[aRowIndex].Tiles;
                    if (aTileIndex < 0 || aTileIndex >= tiles.Count)
                    {
                        return(null);
                    }

                    return(string.Join(" ",
                                       from t in tiles
                                       .Skip(aTileIndex)
                                       .Take(bTileIndex + 1 - aTileIndex)
                                       select GetTileText(t)));
                }

                // first row
                // A.X
                tiles = textPart.Rows[aRowIndex].Tiles;
                if (aTileIndex < 0 || aTileIndex >= tiles.Count)
                {
                    return(null);
                }
                sb.Append(string.Join(" ",
                                      from t in tiles.Skip(aTileIndex)
                                      select GetTileText(t)));

                // mid-rows
                for (int i = aRowIndex + 1; i < bRowIndex; i++)
                {
                    sb.AppendLine();
                    sb.Append(string.Join(" ",
                                          from t in textPart.Rows[i].Tiles
                                          select GetTileText(t)));
                }

                // last row
                sb.AppendLine();
                tiles = textPart.Rows[bRowIndex].Tiles;
                if (bTileIndex < 0 || bTileIndex >= tiles.Count)
                {
                    return(null);
                }
                sb.Append(string.Join(" ",
                                      from t in tiles.Take(bTileIndex + 1)
                                      select GetTileText(t)));

                return(sb.ToString());
            }

            // single tile
            // X
            int tokenIndex = loc.A.X - 1;

            tiles = textPart.Rows[aRowIndex].Tiles;
            return(tokenIndex < 0 || tokenIndex >= tiles.Count
                ? null : GetTileText(tiles[tokenIndex]));
        }
        /// <summary>
        /// Gets the text at the specified location from the specified
        /// base text part.
        /// </summary>
        /// <param name="baseTextPart">The base text part to get text from.</param>
        /// <param name="location">The location.</param>
        /// <returns>The text, or null if location is invalid.</returns>
        /// <exception cref="ArgumentNullException">baseTextPart or location
        /// </exception>
        public override string GetTextAt(IPart baseTextPart, string location)
        {
            if (baseTextPart == null)
            {
                throw new ArgumentNullException(nameof(baseTextPart));
            }
            if (location == null)
            {
                throw new ArgumentNullException(nameof(location));
            }

            if (!(baseTextPart is TokenTextPart textPart))
            {
                return(null);
            }

            // parse
            TokenTextLocation loc = TokenTextLocation.Parse(location);

            string[] tokens;
            int      aLineIndex = loc.A.Y - 1;

            if (aLineIndex < 0 || aLineIndex >= textPart.Lines.Count)
            {
                return(null);
            }

            // range
            if (loc.IsRange)
            {
                // tokens range
                StringBuilder sb = new StringBuilder();

                int bLineIndex = loc.B.Y - 1;
                if (bLineIndex < aLineIndex || bLineIndex >= textPart.Lines.Count)
                {
                    return(null);
                }

                int aTokenIndex = loc.A.X - 1;
                int bTokenIndex = loc.B.X - 1;

                // corner case: same line for A-B
                if (aLineIndex == bLineIndex)
                {
                    // defensive
                    if (bTokenIndex < aTokenIndex)
                    {
                        return(null);
                    }

                    tokens = textPart.Lines[aLineIndex].GetTokens();
                    if (aTokenIndex < 0 || aTokenIndex >= tokens.Length)
                    {
                        return(null);
                    }
                    return(string.Join(" ",
                                       tokens.Skip(aTokenIndex).Take(bTokenIndex + 1 - aTokenIndex)));
                }

                // first line
                // A.X
                tokens = textPart.Lines[aLineIndex].GetTokens();
                if (aTokenIndex < 0 || aTokenIndex >= tokens.Length)
                {
                    return(null);
                }
                sb.Append(string.Join(" ", tokens.Skip(aTokenIndex)));

                // mid-lines
                for (int i = aLineIndex + 1; i < bLineIndex; i++)
                {
                    sb.AppendLine();
                    sb.Append(textPart.Lines[i].Text);
                }

                // last line
                sb.AppendLine();
                tokens = textPart.Lines[bLineIndex].GetTokens();
                if (bTokenIndex < 0 || bTokenIndex >= tokens.Length)
                {
                    return(null);
                }
                sb.Append(string.Join(" ", tokens.Take(bTokenIndex + 1)));

                return(sb.ToString());
            }

            // single token
            // X
            int tokenIndex = loc.A.X - 1;

            tokens = textPart.Lines[aLineIndex].GetTokens();
            return(tokenIndex < 0 || tokenIndex >= tokens.Length
                ? null : tokens[tokenIndex]);
        }