Skip to content

Commit 9762e78

Browse files
added robitcs project
1 parent 1147058 commit 9762e78

19 files changed

+1042
-0
lines changed

RoboticsMaster/Robotics/Chips/Chip.cs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
3+
using Robotics.Extensions;
4+
5+
namespace Robotics.Chips
6+
{
7+
/// <summary>
8+
/// Base class for chips used by Robot. An abstract base class was chosen
9+
/// over an interface because there are certain utility methods that can be shared
10+
/// such as TestIfTypesAreTheSame which insures operations are performed on arrays
11+
/// containing only the same type.
12+
/// </summary>
13+
public abstract class Chip
14+
{
15+
/// <summary>
16+
/// Operation performed by chip. Operations are performed on numeric values. As
17+
/// the only way to determine numeric values is via code (such as a switch statement)
18+
/// a generic is permitted but the data will be validate as numeric (byte, int, double,
19+
/// decimal, etc.).
20+
/// </summary>
21+
/// <param name="data">array of values to be processed</param>
22+
/// <returns>result of processing. For scalar results an array of length 1 is returned
23+
/// with the 0th element set to the scalar value</returns>
24+
public abstract T[] Operation<T>(T[] data);
25+
26+
/// <summary>
27+
/// Tests is data contains numerica data (byte, int, double, etc.)
28+
/// and throws an exception ArgumentException is thrown if type is
29+
/// not numeric
30+
/// </summary>
31+
/// <typeparam name="T">Data type of array (must be numeric)</typeparam>
32+
/// <param name="data">A null or a zero length array is illegal.
33+
/// All types in array are checked if the values are numeric and identical</param>
34+
protected static void TestIfTypesAllTheSameNumeric<T>(T[] data)
35+
{
36+
// The data.IsHomogeneous is to make sure that T is IComparable
37+
// and data[0] is a byte (a legal numeric) but the next value
38+
// could be a string. T.IsNumericType is not legal for the compiler.
39+
if ((data == null) ||
40+
(data.Length == 0) ||
41+
(!data[0].IsNumericType()) ||
42+
(!data.IsHomogeneous()))
43+
{
44+
throw new ArgumentException(
45+
$"{nameof(Operation)} requires data types to be numeric.");
46+
}
47+
}
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System;
2+
using System.Collections;
3+
4+
using Robotics.Extensions;
5+
6+
namespace Robotics.Chips
7+
{
8+
/// <summary>
9+
/// Chip for Robot that allows a Robot to sort data.
10+
/// </summary>
11+
public class ChipOfSorts : Chip
12+
{
13+
public enum SortDirection
14+
{
15+
Ascending,
16+
Descending
17+
}
18+
19+
private SortDirection _sortDirection;
20+
21+
public SortDirection Direction => _sortDirection;
22+
23+
private class SortDescending : IComparer
24+
{
25+
public int Compare(object x, object y)
26+
{
27+
return -1 * ((IComparable)x).CompareTo(y);
28+
}
29+
}
30+
31+
/// <summary>
32+
/// Chip allows robot to sort data in ascending or descending order
33+
/// </summary>
34+
/// <param name="sortDirection">Specifies sort direction ascent or descending</param>
35+
public ChipOfSorts(SortDirection sortDirection)
36+
{
37+
_sortDirection = sortDirection;
38+
}
39+
40+
/// <summary>
41+
/// Returns new array with data in sorted order.
42+
/// </summary>
43+
/// <param name="data">data to be sorted. If values is null then return value is null.
44+
/// All values in the data array must be of the same type or and ArgumentException
45+
/// is thrown </param>
46+
/// <returns>data sorted based off SortDirection specified in the class constructor</returns>
47+
public override T[] Operation<T>(T[] data)
48+
{
49+
if (data == null)
50+
{
51+
return data;
52+
}
53+
54+
TestIfTypesAllTheSameNumeric(data);
55+
// Array.Sort is destructive so clone array first
56+
T[] result = (T[])data.Clone();
57+
58+
// Note from specification:
59+
// Sorting algorythm is not important, use standard one
60+
// from any library you want.
61+
if (_sortDirection == SortDirection.Ascending)
62+
{
63+
Array.Sort(result);
64+
}
65+
66+
else
67+
{
68+
Array.Sort(result, new SortDescending());
69+
}
70+
71+
return result;
72+
}
73+
}
74+
}
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.Reflection;
3+
4+
using Robotics.Extensions;
5+
6+
namespace Robotics.Chips
7+
{
8+
/// <summary>
9+
/// Chip for Robot that allows Robot to sum data
10+
/// </summary>
11+
public class TotalChip : Chip
12+
{
13+
private static T Add<T>(object x, object y)
14+
{
15+
return (T)Convert.ChangeType((dynamic)x + (dynamic)y, typeof(T));
16+
}
17+
/// <summary>
18+
/// Returns the sum (opeator+) of all values in data array via the zeroth element
19+
/// of the returned array. The reason a scaler is not returned is due to a inconsistency
20+
/// in the design requriments namely that chips can return arrays or scalars so the
21+
/// 0th element is used to return the
22+
/// FYI: name does not match other chips naming pattern (name specified by PM)
23+
/// </summary>
24+
/// <param name="data">An array of values of the same Type where said type must contain operator+</param>
25+
/// <returns>if data is null, value returned in null otherwise returns sum of all elements in data.
26+
/// all values in data array</returns>
27+
public override T[] Operation<T>(T[] data)
28+
{
29+
if (data == null)
30+
{
31+
return data;
32+
}
33+
34+
TestIfTypesAllTheSameNumeric(data);
35+
36+
T[] result = { default(T) };
37+
38+
foreach (T datum in data)
39+
{
40+
result[0] += (dynamic)datum;
41+
}
42+
43+
return result;
44+
}
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
3+
namespace Robotics.Extensions
4+
{
5+
/// <summary>
6+
/// Extensions to the Array class.
7+
/// </summary>
8+
public static class ArrayExtensions
9+
{
10+
/// <summary>
11+
/// Returns true if every value in an array is of the same type.
12+
/// </summary>
13+
/// <param name="array">Array for which homogeneity is determined.
14+
/// This value can be null.</param>
15+
/// <returns>return true if array is null or array has a Length of 1 (since is a homogeneous case).
16+
/// Returns true if all values in array have the same Type (via GetType()) and
17+
/// false otherwise</returns>
18+
public static bool IsHomogeneous(this Array array)
19+
{
20+
// when called as an extenion method this cannot be null but if this
21+
// is called as a method it can be null so it can be checked.
22+
if ((array == null) || (array.Length == 0))
23+
{
24+
return true;
25+
}
26+
27+
28+
Type masterType = array.GetValue(0).GetType();
29+
30+
for (int i = 1; i < array.Length; i++)
31+
{
32+
if (!array.GetValue(i).GetType().Equals(masterType))
33+
{
34+
return false;
35+
}
36+
}
37+
38+
return true;
39+
}
40+
41+
/// <summary>
42+
/// Returns true if every value in an array is of the same numeric type.
43+
/// </summary>
44+
/// <param name="array">Array for which homogeneity is determined being all of a single
45+
/// numberic type. If null or zero lenth then the type cannot be numeric so return
46+
/// value is false</param>
47+
/// <returns>return false if array is null or array has a Length of 0 since no numeric type
48+
/// can be detected. Returns true if all values in array have the same Type (via GetType())
49+
/// and if this type is a C#/CLI numeric. Returns false otherwise</returns>
50+
public static bool IsHomogeneousNumericType(this Array array)
51+
{
52+
// when called as an extenion method this cannot be null but if this
53+
// is called as a method it can be null so it can be checked.
54+
if ((array == null) || (array.Length == 0) || (!array.GetValue(0).IsNumericType()))
55+
{
56+
return false;
57+
}
58+
59+
return IsHomogeneous(array);
60+
}
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
3+
namespace Robotics.Extensions
4+
{
5+
public static class ObjectExtensions
6+
{
7+
public static bool IsNumericType(this object o)
8+
{
9+
switch (Type.GetTypeCode(o.GetType()))
10+
{
11+
case TypeCode.Byte:
12+
case TypeCode.SByte:
13+
case TypeCode.UInt16:
14+
case TypeCode.UInt32:
15+
case TypeCode.UInt64:
16+
case TypeCode.Int16:
17+
case TypeCode.Int32:
18+
case TypeCode.Int64:
19+
case TypeCode.Decimal:
20+
case TypeCode.Double:
21+
case TypeCode.Single:
22+
return true;
23+
}
24+
25+
return false;
26+
}
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using System.Reflection;
3+
4+
namespace Robotics.Extensions
5+
{
6+
/// <summary>
7+
/// Extensions to the Type class which includes getting operator+ for a Type.
8+
/// In a production environment this could be extended to get all operator types
9+
/// (-, less than, greater than, etc.) based off the standard names given these
10+
/// overloads by the compiler (op_Inequality, op_GreaterThan, op_Subtraction, etc.)
11+
/// </summary>
12+
public static class TypeExtensions
13+
{
14+
private const string OperatorPlustMethodName = "op_Addition";
15+
16+
/// <summary>
17+
/// Returns the method associated with operator+ for a given type
18+
/// There is no value returned for numeric types (int32,
19+
/// int64, double, float, etc.) and there is no value returned for string
20+
/// </summary>
21+
/// <param name="type"></param>
22+
/// <returns>Returns operator method for specified type or null of
23+
/// operator+ is not associated with the give type.</returns>
24+
public static MethodInfo GetOperatorAddition(this Type type)
25+
{
26+
if (type == null)
27+
{
28+
throw new ArgumentNullException(
29+
$"{nameof(TypeExtensions)}.{nameof(GetOperatorAddition)} value of " +
30+
$"{nameof(type)} cannot be null,");
31+
}
32+
33+
return type.GetMethod(
34+
OperatorPlustMethodName,
35+
BindingFlags.Static | BindingFlags.Public);
36+
}
37+
}
38+
}

RoboticsMaster/Robotics/MainFile.cs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* The instruction specified:
3+
* There is no right or wrong solution as long as code works, but we give bonus points
4+
* for a plain-text explanation on why particular design decisions were made and what
5+
* are the tradeoffs. Put it right into the code in a form of a comment at the
6+
* beginning of the main file.
7+
*
8+
* Design Decision 1: there is no need for a main file. This file, mainfile,
9+
* was include per-instructions above out of respect for the product manager.
10+
*
11+
* Design Decision 2: Units tests were used as "a console application with a test
12+
* method or two" is not the way projects are tested. This is 2000 era development so
13+
* Unit Test are simply more natural.
14+
*
15+
* Design Decision 3: I do not write software as a single file. Applications regardless
16+
* of size are developed using solutions/projets/assemblies and unit tests. I will
17+
* provided both a single file and a full implementation that can be gloned via
18+
* GitHub.com
19+
*
20+
* Design Decision 4: all design decisions are discussed in the context of where
21+
* apply directly since there is no true MainFile. Since this is a bonus question
22+
* explanations will be repeated:
23+
* 1) Chip is the abstract base class of call chips and Operation method is used
24+
* by a Robot to invoke a chip's action
25+
* public abstract T[] Operation<T>(T[] data);
26+
* 2) There is no way to make a generic type T numeric. An Extension method
27+
* was created for the object type ObjectExtensions.IsNumericType which
28+
* determines if a give type in an array of data is numeric (aka is value one
29+
* of byte, int, double, decimal, etc.)
30+
* 3) With generics we could have a case when an array is say IComparable and contains
31+
* mixed numeric types. This cannot be supported easily so it is q requirement that
32+
* all data in array is composted of the same numeric type (see extension method
33+
* ArrayExtensions.IsHomogeneousNumericType).
34+
* 4) There is an inconsistency in the designing. ChipOfSorts returns an array and
35+
* TotalChip returns scalar. To simplify this the scalar, return an array of length
36+
* 1 with the 0th value element set to the scalar result.
37+
* 5) The names provided are not consistent: TotalChip and ChipOfSorts so we put our
38+
* faith in the PM and left the names the same.
39+
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyTitle("Robotics")]
9+
[assembly: AssemblyDescription("")]
10+
[assembly: AssemblyConfiguration("")]
11+
[assembly: AssemblyCompany("")]
12+
[assembly: AssemblyProduct("Robotics")]
13+
[assembly: AssemblyCopyright("Copyright © 2017")]
14+
[assembly: AssemblyTrademark("")]
15+
[assembly: AssemblyCulture("")]
16+
17+
// Setting ComVisible to false makes the types in this assembly not visible
18+
// to COM components. If you need to access a type in this assembly from
19+
// COM, set the ComVisible attribute to true on that type.
20+
[assembly: ComVisible(false)]
21+
22+
// The following GUID is for the ID of the typelib if this project is exposed to COM
23+
[assembly: Guid("7451dee6-a65e-4f81-a64d-b6b4f414ed4b")]
24+
25+
// Version information for an assembly consists of the following four values:
26+
//
27+
// Major Version
28+
// Minor Version
29+
// Build Number
30+
// Revision
31+
//
32+
// You can specify all the values or you can default the Build and Revision Numbers
33+
// by using the '*' as shown below:
34+
// [assembly: AssemblyVersion("1.0.*")]
35+
[assembly: AssemblyVersion("1.0.0.0")]
36+
[assembly: AssemblyFileVersion("1.0.0.0")]

0 commit comments

Comments
 (0)