A7c22254d91baa9ca18786a9d46549f0

A lot of refactoring finally resulted in this long method. I think the code is quite clean and easy to understand. It uses linq a lot, and I'm not really familiar with linq yet, so I figured there are some improvements possible in this area. Also, I'd like to split this method up a bit, so VS does not complain about the admittedly big LOC.

protected override Dictionary<GloballyFilteredPositionSource, DevicePosition> Reconfigure (
			Dictionary<GloballyFilteredPositionSource, DevicePosition> positions)
		{
			/*
			 * with world unset, return current positions.
			 */
			if (World == null) {
				return positions;
			}

			/*
			 * gather all valid volumes
			 */
			List<Volume> projectionVolumes = new List<Volume> ();

			foreach (Room r in World.GetRooms ()) {
				if ("1".Equals (r.GetAttribute (WantDeviceConstant))) {
					projectionVolumes.Add (r.Volume);
				}
			}

			/*
			 * create precomputed distance info
			 */
			var compositions =
				/*
				 * for each combination...
				 */
				from src in positions
				from target in projectionVolumes

				/*
				 * remove invalid positions
				 */
				where src.Value != null

				/*
				 * create bunch of info
				 */
				select new {
					Pair = src,
					Target = target,
					Dist = target.Dist (src.Value.Position),
				};

			/*
			 * apply filter
			 */
			compositions = compositions.Where (x => x.Dist < MaxDist);

			/*
			 * presort
			 */
			compositions = compositions.OrderBy (x => x.Dist);

			/*
			 * store result
			 */
			compositions = compositions.ToList ();

			/*
			 * find and store best matches
			 */
			Dictionary<GloballyFilteredPositionSource, DevicePosition> resultingMatches
				= new Dictionary<GloballyFilteredPositionSource, DevicePosition> (positions);

			while (compositions.Any ()) {
				/*
				 * find best assignment
				 */
				var bestMatch = compositions.First ();

				/*
				 * remove used sources and destinations
				 */
				compositions = compositions.Where (x => x.Pair.Key != bestMatch.Pair.Key);
				compositions = compositions.Where (x => x.Target != bestMatch.Target);
				compositions = compositions.ToList (); // tested: improves performance

				/*
				 * ultimately add current pair to results
				 */
				DevicePosition dpResult = new DevicePosition (
					bestMatch.Target.Center,
					bestMatch.Pair.Value.Time);
				resultingMatches[bestMatch.Pair.Key] = dpResult;
			}

			return resultingMatches;
		}

Refactorings

No refactoring yet !

A7c22254d91baa9ca18786a9d46549f0

mafutrct

July 9, 2009, July 09, 2009 11:11, permalink

No rating. Login to rate!

I fooled around with the code some more and this is the result so far.

protected override Dictionary<GloballyFilteredPositionSource, DevicePosition> Reconfigure (
			Dictionary<GloballyFilteredPositionSource, DevicePosition> rawPositions)
		{
			/*
			 * with world unset, return current positions.
			 */
			if (World == null) {
				return rawPositions;
			}

			/*
			 * remove invalid positions
			 */
			var positions = rawPositions.Where (x => x.Value != null);

			/*
			 * create precomputed distance info
			 */
			IEnumerable<Composition> compositions = CreateCompositions (positions);

			/*
			 * find and store best matches
			 */
			var resultingMatches = new Dictionary<GloballyFilteredPositionSource, DevicePosition> ();
			foreach (var pos in positions) {
				resultingMatches.Add (pos.Key, pos.Value);
			}

			while (compositions.Any ()) {
				/*
				 * find best assignment
				 */
				var bestMatch = compositions.First ();

				/*
				 * remove used sources and destinations
				 */
				compositions = compositions.Where (x => x.Pair.Key != bestMatch.Pair.Key);
				compositions = compositions.Where (x => x.Target != bestMatch.Target);
				compositions = compositions.ToList (); // tested: improves performance

				/*
				 * ultimately add current pair to results
				 */
				DevicePosition dpResult = new DevicePosition (
					bestMatch.Target.Center,
					bestMatch.Pair.Value.Time);
				resultingMatches[bestMatch.Pair.Key] = dpResult;
			}

			return resultingMatches;
		}

		private List<Composition> CreateCompositions (
			IEnumerable<KeyValuePair<GloballyFilteredPositionSource, DevicePosition>> positions)
		{
			/*
			 * gather all valid volumes
			 */
			IEnumerable<Volume> projectionVolumes =
				from room in World.GetRooms ()
				where "1".Equals (room.GetAttribute (WantDeviceConstant))
				select room.Volume;
			projectionVolumes = projectionVolumes.ToList ();

			/*
			 * build all pairs
			 */
			IEnumerable<Composition> compositions =
				from src in positions
				from target in projectionVolumes
				select new Composition (src, target);

			/*
			 * apply filter
			 */
			compositions = compositions.Where (x => x.Dist < MaxDist);
			compositions = compositions.ToList ();

			/*
			 * presort
			 */
			compositions = compositions.OrderBy (x => x.Dist);

			return compositions.ToList ();
		}
Dcc1f0ceeb6e0bdef4c4774005941ad1

Diadistis

July 29, 2009, July 29, 2009 15:30, permalink

No rating. Login to rate!

My take on this

public class Composition
    {
        public KeyValuePair<GloballyFilteredPositionSource, DevicePosition> Pair { get; set; }
        public Room Target { get; set; }
        public float Dist { get; set; }
    }

    ...

        protected Dictionary<GloballyFilteredPositionSource, DevicePosition> Reconfigure(
            Dictionary<GloballyFilteredPositionSource, DevicePosition> positions)
        {
            // with world unset, return current positions.
            if (this.World == null)
            {
                return positions;
            }

            // gather all valid volumes
            var projectionVolumes =
                from r in World.GetRooms()
                where r.GetAttribute(WantDeviceConstant).Equals("1")
                select r;

            // create precomputed distance info
            var originalCompositions =
                // keep valid positions
                from src in positions.Where(x => x.Value != null)
                from target in projectionVolumes
                // create bunch of info
                select new Composition
                {
                    Pair = src,
                    Target = target,
                    Dist = target.Dist(src.Value.Position),
                };

            var finalCompositions = (
                from comp in originalCompositions
                where comp.Dist < MaxDist // filter                
                orderby comp.Dist         // order                
                select comp).ToList();    // store as list

            var resultingMatches = 
                new Dictionary<GloballyFilteredPositionSource, DevicePosition>(positions);

            while (finalCompositions.Any())
            {
                // find best assignment
                var bestMatch = finalCompositions.First();

                // remove used sources and destinations
                finalCompositions = (
                    from comp in finalCompositions
                    where comp != bestMatch
                    select comp).ToList();

                // add current pair to results
                resultingMatches.Add(
                    bestMatch.Pair.Key,
                    new DevicePosition(
                        bestMatch.Target.Center, 
                        bestMatch.Pair.Value.Time));
            }

            return resultingMatches;
        }

Your refactoring





Format Copy from initial code

or Cancel