module model; import std.math; struct Point { float x, y; } float sqr(float v) { return v * v; } float dist()(auto ref const(Point) a, auto ref const(Point) b) { return sqrt(sqr(ax - bx) + sqr(ay - by)); } class Model { float triangleAreaByLengths(float a, float b, float c) { auto p = (a + b + c) / 2; return sqrt(p * (p - a) * (p - b) * (p - c)); } float triangleAreaByPoints(Point a, Point b, Point c) { auto ab = dist(a, b); auto ac = dist(a, c); auto bc = dist(b, c); return triangleAreaByLengths(ab, ac, bc); } }
import std.stdio; import model; void main() { auto a = Point(1, 2); auto b = Point(3, 4); auto c = Point(4, 1); auto m = new Model; writeln(m.triangleAreaByPoints(a, b, c)); }
static MyType fromJson(Json data)
and Json toJson() const
, which describes the process of converting complex structures into Json type, an example . interface IModel { @method(HTTPMethod.GET) float triangleAreaByLengths(float a, float b, float c); @method(HTTPMethod.GET) float triangleAreaByPoints(Point a, Point b, Point c); } class Model : IModel { ... }
@method(HTTPMethod.GET)
decorators @method(HTTPMethod.GET)
required for building routing. There is also a way to do without them - use the naming convention of methods (prefixes):get
, query
- GET
method;set
, put
- PUT
;add
, create
, post
- POST
;remove
, erase
, delete
- DELETE
;update
patch
- PATCH
. shared static this() { auto router = new URLRouter; router.registerRestInterface(new Model); // auto set = new HTTPServerSettings; set.port = 8080; set.bindAddresses = ["127.0.0.1"]; listenHTTP(set, router); }
... auto m = new RestInterfaceClient!IModel("http://127.0.0.1:8080/"); // ...
interface IPointCalculator { struct CollectionIndices { string _name; } // @method(HTTPMethod.GET) Point calc(string _name, Point[] points...); } interface IModel { ... @method(HTTPMethod.GET) Collection!IPointCalculator calculator(); } class PointCalculator : IPointCalculator { Point calc(string _name, Point[] points...) { import std.algorithm; if (_name == "center") { auto n = points.length; float cx = points.map!"ax".sum / n; float cy = points.map!"ay".sum / n; return Point(cx, cy); } else if (_name == "left") return points.fold!((a,b)=>ax<bx?a:b); else throw new Exception("Unknown calculator '" ~ _name ~ "'"); } } class Model : IModel { PointCalculator m_pcalc; this() { m_pcalc = new PointCalculator; } ... Collection!IPointCalculator calculator() { return Collection!IPointCalculator(m_pcalc); } }
IPointCalculator
is not a collection element, but the collection itself and the CollectionIndices
structure just indicates the presence of indices used to obtain the elements of this collection. The underscore before _name
determines the format of the request to the calc
method as calculator/:name/calc
, where :name
then passed as the first parameter to the method, and CollectionIndices
allows you to build such a query when implementing the interface using a new RestInterfaceClient!IModel
. ... writeln(m.calculator["center"].calc(a, b, c)); ...
Collection!IPointCalculator
to IPointCalculator
then little will change: ... writeln(m.calculator.calc("center", a, b, c)); ...
Collection
in this combination is not entirely clear. html head title REST style. .label { display: inline-block; width: 20px; } input { width: 100px; } script(src = "model.js") script. function getPoints() { var ax = parseFloat(document.getElementById('ax').value); var ay = parseFloat(document.getElementById('ay').value); var bx = parseFloat(document.getElementById('bx').value); var by = parseFloat(document.getElementById('by').value); var cx = parseFloat(document.getElementById('cx').value); var cy = parseFloat(document.getElementById('cy').value); return [{x:ax, y:ay}, {x:bx, y:by}, {x:cx, y:cy}]; } function calcTriangleArea() { var p = getPoints(); IModel.triangleAreaByPoints(p[0], p[1], p[2], function(r) { document.getElementById('area').innerHTML = r; }); } body h1 div div.label A: input#ax(placehoder="ax",value="1") input#ay(placehoder="ay",value="2") div div.label B: input#bx(placehoder="bx",value="2") input#by(placehoder="by",value="1") div div.label C: input#cx(placehoder="cx",value="0") input#cy(placehoder="cy",value="0") div button(onclick="calcTriangleArea()") p : span#area
... auto restset = new RestInterfaceSettings; restset.baseURL = URL("http://127.0.0.1:8080/"); router.get("/model.js", serveRestJSClient!IModel(restset)); router.get("/", staticTemplate!"index.dt"); ...
this.
For these fields in the js object) and for collections in particular (incorrect generation of url - :name
doesn’t matter replaced). But these roughnesses are easily repairable, I think they will be fixed in the near future .Source: https://habr.com/ru/post/310268/
All Articles