diff --git a/README-gv319.md b/README-gv319.md index 384c25b..3109542 100644 --- a/README-gv319.md +++ b/README-gv319.md @@ -1,118 +1,25 @@ # Example README for individual code submission -## Instructions - -* This file should be submitted (changed) on branch `hlp22-indiv-assess-` of either your own repo or your group repo - * replace `` in filename `README-.md` by your login - in his example ` = tomcl` - * name the branch as above, including your login. This branch is used only for your submission. -* A link to the repo and branch must be on the `indiv` sheet of Tom Clarke's Team [google spreadsheet](https://docs.google.com/spreadsheets/d/1prQ5usnpu36FgtbsMO8j6_mwbdd34haSMOQKN2OkLBA/edit?usp=sharing) -* The repo you use **must have your marker added as collaborator** (github login is on indiv assessment spreadsheet page) -* Delete these instructions from your version of this readme -* Delete my comments from your version of the readme (it is an example, not something you add lines to). -Keep the headings and **replace the admin section links and notes with correct ones**. -* Link to the sourcefile your code is contained in (drawblock or symbol) with an absolute hyperlink -to your repo and branch -* Specify which code section and file you are doing as in my ppt (1,2,3), (buswire,symbol) -* Add any changes to my section code allocations. This must be consistent with what has been -recorded in your team's file in my Team contributions repo](https://github.com/tomcl/hlp22docs/blob/main/README.md) -main branch ./TeamN.md (N = 1 - 9) file. The team contrib repo is as official record. This file will be -used marking and should have line numbers for easy access. Expect to be marked down if your marker -cannot easily find everything via links from this README. - -## Team Shared Team.md - -[Team Contribution Repo](https://github.com/tomcl/hlp22docs/blob/main/README.md) - -* A file in this repo file is common to the team contains who is responsible for which parts of code -* Fork and clone it -* Any team member can make agreed by team commits. First commit before Wed 23 Fen 16:00. -* Changes in who does what are recorded by altering list of functions AND -as extra lines in this file. See sample file in [README](https://github.com/tomcl/hlp22docs/blob/main/README.md) - ## Admin and quick access links *link to your teamN.md file* -[Common repo TeamN file](https://github.com/tomcl/hlp22docs/blob/main/README.md) +[Common repo Team 6 file](https://github.com/tomcl/hlp22docs/blob/main/Team6.md) -[Buswire (section 3)](src/renderer/drawblock/buswire.fs) +Link to altered files: +* [Symbol (Section 2)](src/Renderer/DrawBlock/Symbol.fs) +* [Sheet (Section 2)](src/Renderer/DrawBlock/Sheet.fs) +* [Renderer (Section 2)](src/Renderer/Renderer.fs) -Section 3 on my file is lines : 700-1100 -I am also responsible for lines 100-120 (functions mySplurgeFunc, my2ndSplurgeFunc) - -Anything else you need to say about what you are or are not responsible for. - -## Code partitioning notes (don't copy this section in your submitted README - delete it) - -Insert clear comments in the source files indicating where each person's code starts and stops - -``` -//---------------------------------------------------------------------------------// -//--------------------TJWC CODE SECTION STARTS-------------------------------------// -//---------------------------------------------------------------------------------// -``` - -### Separating code into 3 modules (in different files) - -Groups can - **if they wish** - modularise their buswire or symbol files into 2 or 3 modules in separate files - -1. Symbol1 -2. Symbol2 -3. Symbol3 - -With each module referencing the ones before with `open`. - -A top-level module `Symbol` or `BusWire` after these three must contain functions exported anywhere outside symbol so that -references in the rest of the code still work. - -``` -Symbol.fs - -let interface1 = Symbol1.interface1 -let interface2 = Symbol1.Interface2 -let interface3 = Symbol2.interface3 -``` - -### Submodules within one file - -Less dramatic, but still useful for modularity. Groups can - **if they wish** - modularise their buswire or symbol files into 3 submodules inside the existing file - -``` -Symbol.fs - -module symbol1 = - let symbol1defn = ... - -module symbol2 - open symbol1 - let symbol2defn - -module symbol3 = - open symbol1 - open symbol2 - let symbol3 defn = -``` - -Again you will need to mend references - because open Symbol in some other part of Issie would need to become open Symbol.Symbol1, open Symbol.Symbol2 etc to pick up exported code in the submodules. you can add exports to Symbol.fs outside the three submodules as -when each moduel is in separate files. - -## Note on assessment - -The aim of assessment if that the first two sections should be fairly straightforward and demonstrate basic knowledge -of how to write FP code. They can achieve overall marks up to 70% without extension work. Those working on -significant extensions should put extra effort into these and not complex analysis section since the -analysis marks can accept well-written code supporting extensions as evidence of understanding. -The aim of this is so that you get marks for good code, -if you can write signiifcant good code without being motivated to write reports. - -There are signiifcant differences between different code sections, and also things which -change dependning on what your base types are and how ambitious your code rewrite it. Ask early -if you are concerned about how this assessment will impact you. There will be ways to reward code -writing which can be found if need be in individual cases. +I am responsible for making the following changes in my code: +* __Symbol.fs:__ Lines : 718-1315 (Section 2) and Lines : 97-102 (stransform_fsm) + - Includes changes to existing code for Section 2 and new functions implementing the extensions. +* __Sheet.fs:__ Lines 86, 859-863 (Extensions) + - Includes changes required to make extensions for rotation work. +* __Renderer.fs:__ Lines 151 (Extensions) + - Includes changes required to make extensions for UI rotation work. ## Code Quality - -This will be assessed based on the code. You can **but do not have to** highlight here things you are particularly proud of and want markers to look at (up to 3) as short bullet points: - +Things to note: * Naming of `myGoodName`, `myWonderfulLongName` * New function boundaries: `topfun` -> `firstfun`, `topfun` -> `secondFun` * New types: MyGoodType @@ -123,72 +30,109 @@ Your code will all be assessed anyway, so this is optional. ## Analysis -This combines analysis of **issues in existing code** with **proof or analysis of how/why the new code works**. -The marking combines both parts. If new code already works and is well written (especially if it is -demonstrated to have significant value in terms of ability to support extensions (see Extensions below) -less evidence will be needed for a high mark in this section. -The analysis here demonstrates that you understand the problems in the old code. -If the old code has no or few problems you can say this. +### Types +_The types decided in the first part of Symbol.fs were `STransform` of type `Rotation` and `PortOrientationOffset` of type {`PortOrientation`,`Offset`} each with its four possible cases to be used to describe +the different rotations fo the symbol and the side of the symbol its ports are at each rotation._ +_`APortOffsetsMap` of type `Map` was used to describe the port locations relative to the top left corner of the symbol. +This map uses string keys `I0..IN` and `O0..ON` to correctly distinguish and store the input and output port offsets in the map._ -Anything you say here may if necessary be tested in the 5 min feedback interview to check understanding. +### Changes to pre-existing code -### Issues in Existing Code -#### Bad Function list +Overall small changes were made to the pre-existing code, as the main focus was the correct implementation +of the extensions and symbol enhancements and to ensure their full functionality. -List any problems with the existing code **concisely** as numbered points one function per point. State why -the problem exists. List only functions with **significant problems**. You can should refer to XML comments -in your refactored code where this helps. You may note the worst 3 functions even if they have problems that are not -significant. +Minor changes were made by removing unnecessary parentheses adding comments where necessary and refactoring the code where unnecessary arguments were passed to functions. -* if function is poorly documented say why this is necessary (what is not obvious from a good name + -* parameter names + types). -* if function has bad name say why this is confusing -* if a function is poorly written indicate what rewriting would improve this (briefly). You can -refer to your code if this helps. -#### Other problems +#### changeLsbf, changeConstantf +Renamed to changeLSBbits and changeConstant respectively to avoid confusion of f being regarded as using an input of type float. -State **concisely** Issues with existing code, or in refactoring for new types, that do not fit into per function list. -Again numbered points, at most 3. Choose the most inmportant if you have too much to say. You can should -refer to documentation (not XML docs) in code where this helps. +#### createCustomPortNamesMap +Removed parantheses and unnecessary use of input parameter n, as it wasn't used and so that it wasn't required when used. + +#### getInputPortsPositionMap, getOutputPortsPositionMap,getPortLocations, getInputPortLocation, getOutputPortLocation +Since getInputPortsPositionMap, getOutputPortsPositionMap are now using getGlobalPortPos which is explained later on in the Extensions section the input parameter of model is not required but only the Symbol list. +Therefore, to avoid confusion and improve readability it was removed as a parameter and as input to the following function addressed above. + +Apart from these changes the main focus was targeted at the Extensions of this Section due to their importance. ### Analysis of how/why code works +The code described below are the fully working implemented Symbol - enhancements for the Individual Coding of Section 2 ([Project Spec: Slide 6](https://intranet.ee.ic.ac.uk/t.clarke/hlp/lectures/project22-spec.pdf)) -This section need not contain analysis if the code can be demonstarted working. In -that case list as bullet points the features you will demonstarte (quickly) in the 5 min -interview. - -* If code works fully and can be demonstrated in the 5 minute feedback interview no analysis is needed. -* If code will be manually tested in interview say what the tests are that supplement your analysis -* Interview code must be the assessed branch (not something else, or using later group code) -* A good way to show code works is to explain how it differs from existing working code and how existing -functionality is preserved. +The code demonstrated in the 5 minute feedback will be to: +* Show different UI implementations to perform rotation for each symbol. +* Show how ports on different symbols are mapped with rotation to the different sides of the symbol. +* Show how the wiring between symbols is also altered with each rotation. +* Show that the bounding box of each symbol changes with each rotation for each symbol. # Extensions +## 1. Locate port position and orientation, given symbol position and orientation +### Changes in files: + - __Symbol.fs__ + - `743-748`canvasPortLocation + - `753-761` getGlobalPortPos -Extensions are required for mark > 70 and optional for mark below 70. High marks on -the first two sections cannot boost extensions mark if this is lower than them. +### Explanation: +Functions `canvasPortLocation` and `getGlobalPortPos` were created to produce the "Global" Coordinates of the ports +for each symbol at any given rotation and position. `canvasPortLocation` extracts the `APortOffsetsMap` of the specified +symbol and returns a list of the global XYPos ports of the symbol by combining the offsets with the top-left corner of the symbol. +These coordinates are shown by toggling Developer tools in Issie and are outputted every time a selected symbol is rotated +showing its global coordinates in the order described in Types. Keep in mind the coordinates shown are those before the symbol is rotated. +Similar to `canvasPortLocation`, `getGlobalPortPos` is used to generate the "Global" XYPos of a specified Port on the Canvas +given the port and symbol specified. Since, the `APortOffset` map and `STransform` are part of the Symbol type, the entire symbol is passed to the function, +rather than these separately. After categorizing the port passed to the function as type input or output, the appropriate index of the port is extracted +and is used as a key to extract the correct coordinates of the port to display and to be used by buswire.fs. Since the `APortOffsetMap` is updated +at every rotation (discussed in later extensions), `getGlobalPortPos` will always receive a new `APortOffsetMap` at every orientation and thus +not require the current orientation as input. This can be tested by rotating a symbol and connecting another symbol's ports to its ports. +It can be observed that the gray circles used to distinguish which ports connection can be made are correctly displayed on the rotated symbol, and +the buswire correctly connects to that rotated port location. However, two issues seem to arise. The wire is connected parallel to the +port, if the symbol is rotated as the `buswire.fs` is expecting the symbol to be non-rotated. Additionally, the `buswire.fs` seems to only +update when the symbol is moved. As a result, a communication between the rotations and orientations of the symbol need to be passed +to `buswire.fs` to ensure that the wires are correctly displayed during rotation. This will be done later on in the group work. -$baseMark = \min (70, code * 20/35 + analysis * 15/35)$ +## 2. UI to rotate symbol +### Changes in files: + - __Symbol.fs__ + - `1164-1173` RotateSymbols compList -$extendedMark = code * 20/50 + analysis * 15/50 + extensions * 15/50$ - -$overallMark = \max (baseMark, extendedMark)$ - -* This section can be missing if you have not done significant extension work. -* Extension code, if well documented (in the code) and clearly written, can be assessed without working - (if it is demonstrated it depends on other people's code not yet written). -* Don't bother writing this section unless you have significant extension work, because the mark here - will usually not be counted in that case (see the marking scheme). Marks for extensions will be awarded -only for work of C level or above. - -* delete the above comemnts and add your satement of extensions as below* - -1. List as numbered points the extensions (features) your code will support - - a. Use nested letters for the functions you have written extra, - or changed, to allow this, and for concise comments concise comments about why they work. + - __Sheet.fs__ + - `86` Type KeyboardMsg Rotate + - `859-863` Keypress Rotate + - __Renderer.fs__ + - `151-152` makeItem "Rotate Symbol" +### Explanation: +The UI was altered to incorporate the use of symbol rotation. Thus was done by first altering the `Renderer.fs`. Line 151 was added +to add the menu item "Rotate Symbol" in order to be able to rotate any symbol selected. This option was then linked through `Sheet.fs` +This functionality can be found on the menu bar under "View". Further implementation was added to rotation by adding a keyboard shortcut. +This was done in line 86 of `Sheet.fs` where the KeybrdMsg "Rotate" was added to implement this. Lines 859-863 were added to link +the menu item and keyboard shortcut "Shift+R" to Symbol.RotateSymbols in `Symbol.fs` to rotate the symbol selected. +The case "RotateSymbols" was added to the "update" function used in `Symbol.fs` to update the symbols on the canvas. As seen in lines +"1164-1173" a new map of symbols, to be displayed and were existing on the canvas, is created where the symbol with the specified id +found after being seelcted, is changed by incrementing its STransform value to the next Rotation using stransform_fsm and +updating the `APortOffsetMap` using RotatePortMap provided by Section 1. Finally, the model Symbols are replaced by these new symbols. +As a result, the selected symbol is updated with its 90 deg rotated version. Worth noting is the addition of the `canvasPortLocation` +function in this case to print the global port locations as explained previously. +The above can be fully tested by selecting a symbol on the canvas and pressing either `Shift+R` or `View > Rotate Symbol`. +The "Global" port coordinates of the selected symbol will also appear in the console if Developer Tools are toggled on. +### 3. Make symbol bounding box work with rotation +### Changes in files: + - __Symbol.fs__ + - `724-727` getBoundingBoxofSymbol + - `728-729` getBoundingBoxes + - `730-731` getOneBoundingBox + +### Explanation: +The function `getBoundingBoxofSymbol` was updated to correctly alter the bounding box border of each symbol by taking into account +the current orientation of the symbol. This is done using the STransform passed from the Symbol as input of the function. This is +used as a match case where the bounding box is altered as `HxW` and `WxH` based on the current orientation of the symbol. +The height and weight of the symbol are passed to the border width and height in order or in reverse. This ensures that for every orientation +of the symbol, the correct border is used. The new `getBoundingBoxofSymbol` function is passed to the `getBoundingBoxes` and `getOneBoundingBox` +to be used by `Sheet.fs` to correctly display the Bounding box of the symbol at each orientation. +This can be tested by selecting the symbol to be tested, then rotated and checking with another symbol whether the bounding box +correctly responds when disrupted. + +The Symbol enhancements for section 2 described above are fully working without producing any errors during build and runtime \ No newline at end of file diff --git a/src/Renderer/DrawBlock/Symbol.fs b/src/Renderer/DrawBlock/Symbol.fs index cd053cf..45dfd74 100644 --- a/src/Renderer/DrawBlock/Symbol.fs +++ b/src/Renderer/DrawBlock/Symbol.fs @@ -101,8 +101,8 @@ let stransform_fsm(prev_state:Rotation):Rotation = | R180 -> R270 | R270 -> R0 -///Insert titles compatible with greater than 1 buswidth -let title t (n) = +///Insert titles compatible with greater than 1 bus width +let title t n = if n = 1 then t else t + "(" + string(n-1) + "..0)" ///Insert titles for bus select @@ -150,13 +150,13 @@ let gateDecoderType (comp:Component) = | AsyncRAM1 _ -> "Async-RAM" | DFF -> "DFF" | DFFE -> "DFFE" - | NbitsXor (x)-> title "N-bits-Xor" x + | NbitsXor x-> title "N-bits-Xor" x | Custom x -> x.Name | _ -> "" let createCustomPortNamesMap inputLabels outputLabels = - let adder x ((name:string),n) (portType:PortType)= + let adder x (name:string,_) (portType:PortType) = let key = match portType with |PortType.Input -> "I"+ string x @@ -241,31 +241,31 @@ let makeComp (pos: XYPos) (comptype: ComponentType) (id:string) (label:string) : failwithf "What? Legacy RAM component types should never occur" | And | Nand | Or | Nor | Xnor | Xor -> (2 , 1, 2*GridSize , 2*GridSize) | Not -> ( 1 , 1, 2*GridSize , 2*GridSize) - | ComponentType.Input (a) -> ( 0 , 1, GridSize , 2*GridSize) - | ComponentType.Output (a) -> ( 1 , 0, GridSize , 2*GridSize) - | ComponentType.Viewer a -> ( 1 , 0, GridSize , GridSize) + | ComponentType.Input _ -> ( 0 , 1, GridSize , 2*GridSize) + | ComponentType.Output _ -> ( 1 , 0, GridSize , 2*GridSize) + | ComponentType.Viewer _ -> ( 1 , 0, GridSize , GridSize) | ComponentType.IOLabel ->( 1 , 1, GridSize , 2*GridSize) | Decode4 ->( 2 , 4 , 4*GridSize , 3*GridSize) - | Constant1 (a, b,_) | Constant(a, b) -> ( 0 , 1, GridSize , 2*GridSize) + | Constant1 _ | Constant _ -> ( 0 , 1, GridSize , 2*GridSize) | MergeWires -> ( 2 , 1, 2*GridSize , 2*GridSize) - | SplitWire (a) ->( 1 , 2 , 2*GridSize , 2*GridSize) + | SplitWire _ ->( 1 , 2 , 2*GridSize , 2*GridSize) | Mux2 -> ( 3 , 1, 3*GridSize , 2*GridSize) // EXTENSION: | Mux4 -> ( 5 , 1, 5*GridSize , 2*GridSize) // EXTENSION: | Mux8 -> ( 9 , 1, 7*GridSize , 2*GridSize) | Demux2 ->( 2 , 2, 3*GridSize , 2*GridSize) // EXTENSION: | Demux4 -> ( 2 , 4, 150 , 50) // EXTENSION: | Demux8 -> ( 2 , 8, 200 , 50) - | BusSelection (a, b) -> ( 1 , 1, GridSize, 2*GridSize) - | BusCompare (a, b) -> ( 1 , 1, GridSize , 2*GridSize) + | BusSelection _ -> ( 1 , 1, GridSize, 2*GridSize) + | BusCompare _ -> ( 1 , 1, GridSize , 2*GridSize) | DFF -> ( 1 , 1, 3*GridSize , 3*GridSize) | DFFE -> ( 2 , 1, 3*GridSize , 3*GridSize) - | Register (a) -> ( 1 , 1, 3*GridSize , 4*GridSize ) - | RegisterE (a) -> ( 2 , 1, 3*GridSize , 4*GridSize) - | AsyncROM1 (a) -> ( 1 , 1, 3*GridSize , 4*GridSize) - | ROM1 (a) -> ( 1 , 1, 3*GridSize , 4*GridSize) - | RAM1 (a) | AsyncRAM1 a -> ( 3 , 1, 3*GridSize , 4*GridSize) - | NbitsXor (n) -> ( 2 , 1, 3*GridSize , 4*GridSize) - | NbitsAdder (n) -> ( 3 , 2, 3*GridSize , 4*GridSize) + | Register _ -> ( 1 , 1, 3*GridSize , 4*GridSize ) + | RegisterE _ -> ( 2 , 1, 3*GridSize , 4*GridSize) + | AsyncROM1 _ -> ( 1 , 1, 3*GridSize , 4*GridSize) + | ROM1 _ -> ( 1 , 1, 3*GridSize , 4*GridSize) + | RAM1 _ | AsyncRAM1 _ -> ( 3 , 1, 3*GridSize , 4*GridSize) + | NbitsXor _ -> ( 2 , 1, 3*GridSize , 4*GridSize) + | NbitsAdder _ -> ( 3 , 2, 3*GridSize , 4*GridSize) | Custom x -> let h = GridSize + GridSize * (List.max [List.length x.InputLabels; List.length x.OutputLabels]) let maxInLength, maxOutLength = customToLength x.InputLabels, customToLength x.OutputLabels @@ -315,8 +315,8 @@ let inline getPortPosEdgeGap (ct: ComponentType) = | _ -> 1.0 let getPortPos (comp: Component) (port:Port) = - let (ports, posX) = - if port.PortType = (PortType.Input) then + let ports, posX = + if port.PortType = PortType.Input then (comp.InputPorts, 0.0) else (comp.OutputPorts, float( comp.W )) @@ -341,8 +341,8 @@ let offsethelper (comp: Component) orientation (port:Port) = match ct with | MergeWires | SplitWire _ -> 0.25 | _ -> 1.0 - let (ports, posX) = - if port.PortType = (PortType.Input) then + let ports, posX = + if port.PortType = PortType.Input then (comp.InputPorts, 0.0) else (comp.OutputPorts, float( comp.W )) @@ -354,7 +354,7 @@ let offsethelper (comp: Component) orientation (port:Port) = /////change name let portListToMap (portList: Port List) (symbol: Symbol) : Map= let adder (symbol: Symbol) (port: Port) = - let num = match port.PortNumber with |Some n -> n |_->(-1) + let num = match port.PortNumber with |Some n -> n |_-> -1 let key = match port.PortType with |PortType.Input -> "I"+ string num @@ -643,9 +643,9 @@ let compSymbol (symbol:Symbol) (comp:Component) (colour:string) (showInputPorts: | ROM1 _ |RAM1 _ | AsyncRAM1 _ -> (addClock 0 h colour opacity) | BusSelection(x,y) -> (addText (float(wR/2)-5.0) ((float(hR)/2.7)-2.0) (bustitle x y) "middle" "normal" "12px") | BusCompare (_,y) -> (addText (float(wR/2)-6.0) (float(hR)/2.7-1.0) ("=" + NumberHelpers.hex(int y)) "middle" "bold" "10px") - | Input (x) -> (addText (float(wR/2)) ((float(hR)/3.0)) (title "" x) "middle" "normal" "12px") - | Output (x) -> (addText (float(wR/2)) ((float(hR)/3.0)) (title "" x) "middle" "normal" "12px") - | Viewer (x) -> (addText (float(w/2)) ((float(h)/2.7)-1.25) (title "" x) "middle" "normal" "9px") + | Input x -> (addText (float(wR/2)) ((float(hR)/3.0)) (title "" x) "middle" "normal" "12px") + | Output x -> (addText (float(wR/2)) ((float(hR)/3.0)) (title "" x) "middle" "normal" "12px") + | Viewer x -> (addText (float(w/2)) ((float(h)/2.7)-1.25) (title "" x) "middle" "normal" "9px") | _ -> [] let olColour, strokeWidth = @@ -714,6 +714,11 @@ let view (model : Model) (dispatch : Msg -> unit) = |> TimeHelpers.instrumentInterval "SymbolView" start + +//---------------------------------------------------------------------------------// +//--------------------GV319 CODE SECTION 2 STARTS-------------------------------------// +//---------------------------------------------------------------------------------// + //------------------------GET BOUNDING BOXES FUNCS--------------------------------used by sheet. // Function that returns the bounding box of a symbol. It is defined by the height and the width as well as the x,y position of the symbol let getBoundingBoxofSymbol (sym:Symbol): BoundingBox = @@ -721,8 +726,7 @@ let getBoundingBoxofSymbol (sym:Symbol): BoundingBox = | R0 | R180 -> {X = float(sym.Pos.X) ; Y = float(sym.Pos.Y) ; H = float(sym.Compo.H) ; W = float(sym.Compo.W)} | R90 | R270 -> {X = float(sym.Pos.X) ; Y = float(sym.Pos.Y) ; H = float(sym.Compo.W) ; W = float(sym.Compo.H)} let getBoundingBoxes (symModel: Model): Map = - Map.map (fun sId (sym:Symbol) -> (getBoundingBoxofSymbol sym)) symModel.Symbols - + Map.map (fun _ (sym:Symbol) -> (getBoundingBoxofSymbol sym)) symModel.Symbols let getOneBoundingBox (symModel: Model) (compid: ComponentId ): BoundingBox = getBoundingBoxofSymbol (Map.find compid symModel.Symbols) @@ -736,43 +740,39 @@ let getSymbolPos (symbolModel: Model) compId = // Function to generate Port Positions of each port from Symbol Location and Orientation // Input: Symbol -> Take the symbol for which to extract positions of ports // Output: XYPos list -> Return a list of XYPos positions of the ports starting from inputs, anticlockwise. -let canvasPortLocation (sym:Symbol) : XYPos list = +let canvasPortLocation (sym:Symbol) : XYPos list = sym.APortOffsetsMap |> Map.toList |> List.map snd - |> List.map (fun prevCoor -> prevCoor.Offset) + |> List.map (fun i -> i.Offset) |> List.map (fun i -> {X=i.X+sym.Pos.X;Y=i.Y + sym.Pos.Y}) // Function to generate the true XYPos of a specified Port on the Canvas given the port and symbol // Input: Symbol, Port -> Take the symbol and the specified port // Output: XYPos-> Return the XYPos position of the ports depending on being inputs or outputs let getGlobalPortPos (sym: Symbol) (port:Port) :XYPos = - let (typePort,ports) = - if port.PortType = (PortType.Input) then + let typePort,ports = + if port.PortType = PortType.Input then ("I",sym.Compo.InputPorts) else ("O",sym.Compo.OutputPorts) let index = float( List.findIndex (fun (p:Port) -> p = port) ports ) (Map.find (typePort + string index) sym.APortOffsetsMap).Offset -let getGlobalPortPosModel (sym: Symbol) (port:Port) = - getGlobalPortPos sym port -/// -/// -let getInputPortsPositionMap (model: Model) (symbols: Symbol list) = +/// It is used in getInputPortLocation for a single port +let getInputPortsPositionMap (symbols: Symbol list) = symbols |> List.collect (fun sym -> List.map (fun p -> sym,p) sym.Compo.InputPorts) - |> List.map (fun (sym,port) -> (InputPortId port.Id, posAdd (getGlobalPortPosModel sym port) (sym.Pos))) + |> List.map (fun (sym,port) -> (InputPortId port.Id, posAdd (getGlobalPortPos sym port) sym.Pos)) |> Map.ofList -/// This is quite slow, because it gets the whole maps. -/// It is used in getOutputPortLocation for a single port!! -/// Bad -let getOutputPortsPositionMap (model: Model) (symbols: Symbol list) = //These function add the coordinates of the symbol too + +/// It is used in getOutputPortLocation for a single port +let getOutputPortsPositionMap (symbols: Symbol list) = symbols |> List.collect (fun sym -> List.map (fun p -> sym,p) sym.Compo.OutputPorts) - |> List.map (fun (sym,port) -> (OutputPortId port.Id , posAdd (getGlobalPortPosModel sym port) (sym.Pos))) + |> List.map (fun (sym,port) -> (OutputPortId port.Id , posAdd (getGlobalPortPos sym port) sym.Pos)) |> Map.ofList ///Returns the port object associated with a given portId @@ -783,12 +783,12 @@ let getPort (symModel: Model) (portId: string) = let getPortLocations (symbolModel: Model) (sIds: ComponentId list) = let getSymbols = symbolModel.Symbols - |> Map.filter (fun sId sym -> List.contains sId sIds) + |> Map.filter (fun sId _ -> List.contains sId sIds) |> Map.toList |> List.map snd - let getInputPortMap = getInputPortsPositionMap symbolModel getSymbols - let getOutputPortMap = getOutputPortsPositionMap symbolModel getSymbols + let getInputPortMap = getInputPortsPositionMap getSymbols + let getOutputPortMap = getOutputPortsPositionMap getSymbols getInputPortMap , getOutputPortMap @@ -799,8 +799,8 @@ let getInputPortLocation (model:Model) (portId: InputPortId) = |> Map.toList |> List.map snd - getInputPortsPositionMap model allSymbols - |> Map.find (portId) + getInputPortsPositionMap allSymbols + |> Map.find portId //Returns the location of an output portId @@ -810,8 +810,8 @@ let getOutputPortLocation (model:Model) (portId : OutputPortId) = |> Map.toList |> List.map snd - getOutputPortsPositionMap model allSymbols - |> Map.find (portId) + getOutputPortsPositionMap allSymbols + |> Map.find portId ///Returns the location of a given portId let getOnePortLocation (symModel: Model) (portId : string) (pType: PortType)= @@ -819,19 +819,18 @@ let getOnePortLocation (symModel: Model) (portId : string) (pType: PortType)= | PortType.Input -> getInputPortLocation symModel (InputPortId portId) | PortType.Output -> - getOutputPortLocation symModel (OutputPortId portId) + getOutputPortLocation symModel (OutputPortId portId) /// Returns the location of a given portId, with better efficiency -/// This is still slow, the ports should be looked up from a map of ports -let getOnePortLocationNew (symModel: Model) (portId : string) (pType: PortType) : XYPos= +let getOnePortLocationNew (symModel: Model) (portId : string) (pType: PortType) : XYPos = symModel.Symbols - |> Map.pick (fun key sym -> + |> Map.pick (fun _ sym -> let comp = sym.Compo if pType = PortType.Input then List.tryFind (fun (po:Port) -> po.Id = portId) comp.InputPorts else List.tryFind (fun (po:Port) -> po.Id = portId) comp.OutputPorts - |> Option.map (fun port -> posAdd (getGlobalPortPosModel sym port) (sym.Pos))) + |> Option.map (fun port -> posAdd (getGlobalPortPos sym port) sym.Pos)) /// Returns the locations of a given input portId and output portId @@ -841,7 +840,7 @@ let getTwoPortLocations (symModel: Model) (inPortId: InputPortId ) (outPortId: O (getOnePortLocationNew symModel inputId PortType.Input, getOnePortLocationNew symModel outputId PortType.Output) /// Interface function to get componentIds of the copied symbols -let getCopiedSymbols (symModel: Model) : (ComponentId list) = +let getCopiedSymbols (symModel: Model) : ComponentId list = symModel.CopiedSymbols |> Map.toList |> List.map fst @@ -976,7 +975,7 @@ let getIndex listSymbols compType = |> (+) 1 |> string -///Generates the number to be put in the title of symbols +///Generates the number to be put in the title of symbols let labelGenNumber (model: Model) (compType: ComponentType) (label : string) = let listSymbols = List.map snd (Map.toList model.Symbols) match compType with @@ -989,7 +988,7 @@ let generateLabel (model: Model) (compType: ComponentType) : string = /// Interface function to paste symbols. Is a function instead of a message because we want an output /// Currently drag-and-drop -let pasteSymbols (symModel: Model) (mPos: XYPos) : (Model * ComponentId list) = +let pasteSymbols (symModel: Model) (mPos: XYPos) : Model * ComponentId list = let createNewSymbol (basePos: XYPos) ((currSymbolModel, pastedIdsList) : Model * ComponentId List) (oldSymbol: Symbol): Model * ComponentId List = let newId = JSHelpers.uuid() let posDiff = posDiff oldSymbol.Pos basePos @@ -1019,11 +1018,11 @@ let pasteSymbols (symModel: Model) (mPos: XYPos) : (Model * ComponentId list) = ((symModel, []), oldSymbolsList) ||> List.fold (createNewSymbol basePos) | [] -> symModel, [] - + /// Given two componentId list of same length and input / output ports that are in list 1, return the equivalent ports in list 2. /// ComponentIds at same index in both list 1 and list 2 need to be of the same ComponentType /// CompIds1 need to be in model.CopiedSymbols -let getEquivalentCopiedPorts (model: Model) (copiedIds) (pastedIds) (InputPortId copiedInputPort, OutputPortId copiedOutputPort) = +let getEquivalentCopiedPorts (model: Model) copiedIds pastedIds (InputPortId copiedInputPort, OutputPortId copiedOutputPort) = let findEquivalentPorts compId1 compId2 = let copiedComponent = model.CopiedSymbols[compId1].Compo let pastedComponent = model.Symbols[compId2].Compo // TODO: These can be different for an output gate for some reason. @@ -1087,7 +1086,7 @@ let changeNumberOfBitsf (symModel:Model) (compId:ComponentId) (newBits : int) = {symbol with Compo = newcompo} // Helper function to change the number of bits expected in the LSB port of BusSelection and BusCompare -let changeLsbf (symModel:Model) (compId:ComponentId) (newLsb:int64) = +let changeLSBbits (symModel:Model) (compId:ComponentId) (newLsb:int64) = let symbol = Map.find compId symModel.Symbols let newcompotype = match symbol.Compo.Type with @@ -1098,7 +1097,8 @@ let changeLsbf (symModel:Model) (compId:ComponentId) (newLsb:int64) = let newcompo = {symbol.Compo with Type = newcompotype} {symbol with Compo = newcompo} -let changeConstantf (symModel:Model) (compId:ComponentId) (constantVal:int64) (constantText: string) = +// Helper function to change the name and value of a Constant Symbol +let changeConstant (symModel:Model) (compId:ComponentId) (constantVal:int64) (constantText: string) = let symbol = Map.find compId symModel.Symbols let newcompotype = match symbol.Compo.Type with @@ -1116,7 +1116,7 @@ let update (msg : Msg) (model : Model): Model*Cmd<'a> = { model with Symbols = newSymbols }, Cmd.none //filters out symbol with a specified id | AddSymbol (pos,compType, lbl) -> - let (newModel, _) = addSymbol model pos compType lbl + let newModel, _ = addSymbol model pos compType lbl newModel, Cmd.none | CopySymbols compIds -> @@ -1159,15 +1159,16 @@ let update (msg : Msg) (model : Model): Model*Cmd<'a> = let resetSymbols = Map.map (fun _ sym -> { sym with Colour = "Lightgray"; Opacity = 1.0 }) model.Symbols let newSymbols = (List.fold (fun prevSymbols sId -> Map.add sId {resetSymbols[sId] with Colour = "lightgreen"} prevSymbols) resetSymbols compList) - { model with Symbols = newSymbols }, Cmd.none + { model with Symbols = newSymbols }, Cmd.none - | RotateSymbols compList -> //select a symbol to Rotate + | RotateSymbols compList -> // NEW: select a symbol to Rotate let resetSymbols = Map.map (fun _ sym -> { sym with Colour = "Lightgray"; Opacity = 1.0 }) model.Symbols - let newSymbols = - // if ctrl is pressed make yellow initially, then try to change STransform for every time ctrl+R is pressed + let newSymbols = + // The selected symbol is rotated by incrementing Stransform rotation and updating new APortOffsetsMap and Symbol Pos List.fold (fun prevSymbols sId -> Map.add sId {model.Symbols[sId] with STransform = stransform_fsm(model.Symbols[sId].STransform); APortOffsetsMap = rotatePortMap model.Symbols[sId].APortOffsetsMap model.Symbols[sId]} prevSymbols) resetSymbols compList let result = (canvasPortLocation(model.Symbols[compList[0]])) + //Used to print it Dev Tools Terminal list of ports global coordinates starting anticlockwise from inputs printf "%A" result { model with Symbols = newSymbols }, Cmd.none @@ -1209,13 +1210,13 @@ let update (msg : Msg) (model : Model): Model*Cmd<'a> = { model with Symbols = newSymbolsWithChangedSymbol }, Cmd.none | ChangeLsb (compId, newLsb) -> - let newsymbol = changeLsbf model compId newLsb + let newsymbol = changeLSBbits model compId newLsb let symbolswithoutone = model.Symbols.Remove compId let newSymbolsWithChangedSymbol = symbolswithoutone.Add (compId, newsymbol) { model with Symbols = newSymbolsWithChangedSymbol }, Cmd.none | ChangeConstant (compId, newVal, newText) -> - let newsymbol = changeConstantf model compId newVal newText + let newsymbol = changeConstant model compId newVal newText let symbolswithoutone = model.Symbols.Remove compId let newSymbolsWithChangedSymbol = symbolswithoutone.Add (compId, newsymbol) { model with Symbols = newSymbolsWithChangedSymbol }, Cmd.none @@ -1227,7 +1228,7 @@ let update (msg : Msg) (model : Model): Model*Cmd<'a> = comps |> List.map ( fun comp -> ( let xyPos = {X = float comp.X; Y = float comp.Y} - let (h,w) = + let h,w = if comp.H = -1 && comp.W = -1 then let comp' = makeComp xyPos comp.Type comp.Id comp.Label comp'.H,comp'.W @@ -1284,9 +1285,9 @@ let update (msg : Msg) (model : Model): Model*Cmd<'a> = let comp = symbol.Compo let newCompType = match comp.Type with - | RAM1 mem | AsyncRAM1 mem -> memory - | ROM1 mem -> memory - | AsyncROM1 mem -> memory + | RAM1 _ | AsyncRAM1 _ -> memory + | ROM1 _ -> memory + | AsyncROM1 _ -> memory | _ -> printfn $"Warning: improper use of WriteMemoryType on {comp} ignored" comp.Type @@ -1305,3 +1306,6 @@ let extractComponents (symModel: Model) : Component list = symModel.Symbols |> Map.toList |> List.map (fun (key, _) -> extractComponent symModel key) +//---------------------------------------------------------------------------------// +//--------------------GV319 CODE SECTION 2 ENDS-------------------------------------// +//---------------------------------------------------------------------------------// \ No newline at end of file