How can I write find-instance in def-rule in CLIPS? - syntax-error

What is Wrong with this defrule as it always give me this error
[PRNTUTIL2] Syntax Error: Check appropriate syntax for defrule.
ERROR:
(defrule MAIN::print-university-info
?university <- (object (is-a University)
(universityName $?name)
(numFaculties $?num)
(faculties ?facultyy $?faculties))
?faculty <- (find-instance (
CLIPS>
the rule is
(defrule print-university-info
?university <- (object (is-a University) (universityName $?name) (numFaculties $?num) (faculties ?facultyy $?faculties))
?faculty <- (find-instance ((?facultyInstance Faculty)) (eq ?facultyy ?facultyInstance))
=>
(printout t "University name: " ?name " Number of faculties: " ?num " Faculties: " ?faculty crlf)
)
the classes are
(
defclass University
(is-a USER)
(slot universityName (type SYMBOL))
(slot numFaculties (type INTEGER))
(multislot faculties (type INSTANCE))
)
(
defclass Faculty
(is-a USER)
(slot facultyName (type STRING))
)
and the instances are
(make-instance Cairo of University (universityName "Cairo") (numFaculties 1) (faculties [FCAI]))
(make-instance FCAI of Faculty (facultyName "FCAI"))
I checked the find-instance by adding this to clips
(find-instance ((?facultyInstance Faculty)) (eq ?facultyInstance [FCAI]))
and it returned this
CLIPS> (find-instance ((?facultyInstance Faculty)) (eq ?facultyInstance [FCAI]))
([FCAI])

Find-instance is a function. To call functions from the conditions of a rule, you need to use the test conditional element. The way you've used find-instance in your rule, CLIPS thinks it's the name of a deftemplate. Typically, there's few if any reasons for calling query functions from the conditions of a rule; for most use cases, you'd call them from the actions of a rule. In the conditions of a rule, use a pattern instead:
CLIPS (6.4 2/9/21)
CLIPS>
(defclass University
(is-a USER)
(slot universityName (type SYMBOL))
(slot numFaculties (type INTEGER))
(multislot faculties (type INSTANCE)))
CLIPS>
(defclass Faculty
(is-a USER)
(slot facultyName (type STRING)))
CLIPS>
(definstances initial
(Cairo of University
(universityName "Cairo")
(numFaculties 1)
(faculties [FCAI]))
(FCAI of Faculty
(facultyName "FCAI")))
CLIPS>
(defrule print-university-info
?university <- (object (is-a University)
(universityName $?name)
(numFaculties $?num)
(faculties ?facultyy $?faculties))
?faculty <- (object (is-a Faculty)
(name ?facultyy))
=>
(printout t "University name: " ?name " Number of faculties: " ?num " Faculties: " ?faculty crlf))
CLIPS> (reset)
CLIPS> (run)
University name: Cairo Number of faculties: 1 Faculties: <Instance-FCAI>
CLIPS>

Related

How to convert a class expression (from restriction unionOf) to a string?

A SPARQL query returns a result with restrictions with allValuesFrom and unionOf. I need do concat these values, but, when I use bind or str functions, the result is blank.
I tried bind, str and group_concat functions, but, all of it was unsuccessful. Group_concat return a blank node.
SELECT DISTINCT ?source ?is_succeeded_by
WHERE {
?source rdfs:subClassOf ?restriction .
?restriction owl:onProperty j.0:isSucceededBy .
?restriction owl:allValuesFrom ?is_succeeded_by .
FILTER (REGEX(STR(?source), 'gatw-Invoice_match'))
}
Result of SPARQL query in Protegé:
You can hardly obtain strings like 'xxx or yyy' programmatically in Jena,
since it is Manchester Syntax, an OWL-API native format, and it is not supported by Jena.
Any class expression is actually b-node, there are no such builtin symbols like 'or' in raw RDF.
To represent any anonymous class expression as a string, you can use ONT-API,
which is a jena-based OWL-API, and, therefore, both SPARQL and Manchester Syntax are supported there.
Here is an example based on pizza ontology:
// use pizza, since no example data provided in the question:
IRI pizza = IRI.create("https://raw.githubusercontent.com/owlcs/ont-api/master/src/test/resources/ontapi/pizza.ttl");
// get OWLOntologyManager instance from ONT-API
OntologyManager manager = OntManagers.createONT();
// as extended Jena model:
OntModel model = manager.loadOntology(pizza).asGraphModel();
// prepare query that looks like the original, but for pizza
String txt = "SELECT DISTINCT ?source ?is_succeeded_by\n" +
"WHERE {\n" +
" ?source rdfs:subClassOf ?restriction . \n" +
" ?restriction owl:onProperty :hasTopping . \n" +
" ?restriction owl:allValuesFrom ?is_succeeded_by .\n" +
" FILTER (REGEX(STR(?source), 'Am'))\n" +
"}";
Query q = new Query();
q.setPrefixMapping(model);
q = QueryFactory.parse(q, txt, null, Syntax.defaultQuerySyntax);
// from owlapi-parsers package:
OWLObjectRenderer renderer = new ManchesterOWLSyntaxOWLObjectRendererImpl();
// from ont-api (although it is a part of internal API, it is public):
InternalObjectFactory iof = new SimpleObjectFactory(manager.getOWLDataFactory());
// exec SPARQL query:
try (QueryExecution exec = QueryExecutionFactory.create(q, model)) {
ResultSet res = exec.execSelect();
while (res.hasNext()) {
QuerySolution qs = res.next();
List<Resource> vars = Iter.asStream(qs.varNames()).map(qs::getResource).collect(Collectors.toList());
if (vars.size() != 2)
throw new IllegalStateException("For the specified query and valid OWL must not happen");
// Resource (Jena) -> OntCE (ONT-API) -> ONTObject (ONT-API) -> OWLClassExpression (OWL-API)
OWLClassExpression ex = iof.getClass(vars.get(1).inModel(model).as(OntClass.class)).getOWLObject();
// format: 'class local name' ||| 'superclass string in ManSyn'
System.out.println(vars.get(0).getLocalName() + " ||| " + renderer.render(ex));
}
}
The output:
American ||| MozzarellaTopping or PeperoniSausageTopping or TomatoTopping
AmericanHot ||| HotGreenPepperTopping or JalapenoPepperTopping or MozzarellaTopping or PeperoniSausageTopping or TomatoTopping
Used env: ont-api:2.0.0, owl-api:5.1.11, jena-arq:3.13.1

How can I use CONCAT with results from GROUP_CONCAT in SPARQL?

I have trouble with a SPARQL query. I have two graphs: Discipline and Professor. The graph Discipline contains different disciplines and is linked with the Professor thanks to his id. For example, I have:
<http://www.rdcproject.com/graph/disciplines> {
<http://www.rdfproject.com/77803>
a <http://www.rdfproject.com/Discipline> ;
<http://www.rdfproject.com/cfu>
"6" ;
<http://www.rdfproject.com/disciplineAbbreviation>
"SE" ;
<http://www.rdfproject.com/disciplinename>
"Software Engineering" ;
<http://www.rdfproject.com/hasCourseof>
<http://www.rdfproject.com/8028> ;
<http://www.rdfproject.com/idDiscipline>
"77803" ;
<http://www.rdfproject.com/isTaughtBy>
<http://www.rdfproject.com/0009004> ,
<http://www.rdfproject.com/0004003> ;
<http://www.rdfproject.com/obligatory>
"false" ;
<http://www.rdfproject.com/semester>
"1" ;
<http://www.rdfproject.com/totalhours>
"50" ;
<http://www.rdfproject.com/weekhours>
"5" ;
<http://www.rdfproject.com/year>
"1" .
}
This course is taught by two professors:
<http://www.rdfproject.com/0009004>
a <http://www.rdfproject.com/Teacher> ;
<http://www.rdfproject.com/firstName>
"Koby" ;
<http://www.rdfproject.com/idProfessor>
"0009004" ;
<http://www.rdfproject.com/lastName>
"Bryant" ;
<http://www.rdfproject.com/role>
"contratto" .
<http://www.rdfproject.com/0004003>
a <http://www.rdfproject.com/Teacher> ;
<http://www.rdfproject.com/firstName>
"Lebron" ;
<http://www.rdfproject.com/idProfessor>
"0004003" ;
<http://www.rdfproject.com/lastName>
"James" ;
<http://www.rdfproject.com/role>
"associato" .
Now I want all professors for all disciplines. I have created this query:
PREFIX uni: <http://www.rdfproject.com/>
PREFIX un: <http://www.w3.org/2007/ont/unit#>
SELECT ?idDiscipline ?disciplineName
(CONCAT('[',GROUP_CONCAT(?idProf;separator=","),', ',GROUP_CONCAT(?firstName;separator=","),', ',GROUP_CONCAT(?lastName;separator=","),', ',GROUP_CONCAT(?role;separator=","),']') as ?professors)
FROM <http://www.rdcproject.com/graph/disciplines>
FROM <http://www.rdcproject.com/graph/professor>
WHERE
{
{
?x a uni:Discipline;
uni:disciplinename ?disciplineName;
uni:idDiscipline ?idDiscipline;
uni:disciplineAbbreviation ?sigleDiscipline;
uni:cfu ?cfu;
uni:hasCourseof ?hasCourseof;
uni:obligatory ?obligatory;
uni:semester ?semester;
uni:totalhours ?totalhours;
uni:weekhours ?weekhours;
uni:year ?year;
uni:isTaughtBy ?isTaughtBy.
?isTaughtBy a uni:Teacher;
uni:idProfessor ?idProf;
uni:firstName ?firstName;
uni:role ?role;
uni:lastName ?lastName.
}
}
GROUP BY ?idDiscipline ?disciplineName
This query works fine if a discipline contains only one professor, but in this case the result is:
ID -> 77803"
NAME -> "Software Engineering"
PROFESSOR -> "[0009004,0004003, Kobe,Lebron, Bryant ,James,
contract,contract]"
How can I get this result?
ID -> 77803"
NAME -> "Software Engineering"
PROFESSOR -> "[0009004, Kobe, Bryant, contract]
[0004003, Lebron,James, contract]
Thanks
EDIT:
Thanks to #AKSW
My new Query is:
PREFIX uni: <http://www.rdfproject.com/>
PREFIX un: <http://www.w3.org/2007/ont/unit#>
SELECT ?idDiscipline ?sigleDiscipline ?disciplineName ?cfu ?hasCourseof ?obligatory ?semester ?totalhours ?weekhours ?year
(GROUP_CONCAT(DISTINCT ?prof_str;separator=",") AS ?Professor)
FROM <http://www.rdcproject.com/graph/disciplines>
FROM <http://www.rdcproject.com/graph/professor>
WHERE
{
{
?x a uni:Discipline;
uni:disciplinename ?disciplineName;
uni:idDiscipline ?idDiscipline;
uni:disciplineAbbreviation ?sigleDiscipline;
uni:cfu ?cfu;
uni:hasCourseof ?hasCourseof;
uni:obligatory ?obligatory;
uni:semester ?semester;
uni:totalhours ?totalhours;
uni:weekhours ?weekhours;
uni:year ?year;
uni:isTaughtBy ?isTaughtBy.
?isTaughtBy a uni:Teacher;
uni:idProfessor ?idProf;
uni:firstName ?firstName;
uni:lastName ?lastName;
uni:role ?role.
}
BIND(CONCAT('[',?idProf,',',?firstName,',',?lastName,',',?role,']') AS ?prof_str)
}
GROUP BY ?idDiscipline ?sigleDiscipline ?disciplineName ?cfu ?hasCourseof ?obligatory ?semester ?totalhours ?weekhours ?year

Using React Native MapView in ClojureScript Reagent

I am trying to use MapView from https://github.com/airbnb/react-native-maps using Reagent. It works fine but how could I get local state for MapView when onRegionChange event is fired? Trying to use current/component but it is always nil.
(def Expo (js/require "expo"))
(def map-view (r/adapt-react-class (.-MapView Expo)))
(defn my-map []
(r/create-class
{:component-did-mount (fn [this]
(println "component mount "))
:reagent-render (fn []
(let [this (r/current-component)]
[map-view {:style {:flex 1}
:initialRegion {:latitude 37.78825
:longitude -122.4324
:latitudeDelta 0.0922
:longitudeDelta 0.0421}
:onRegionChange (fn []
;; Would like to see state here.
(println (.. this -state)) )}]))}))
Region information
The onRegionChange callback has Region as argument. Region has the following signature:
type Region {
latitude: Number,
longitude: Number,
latitudeDelta: Number,
longitudeDelta: Number,
}
You can get the values from the Region by using goog.object/get.
If you get the region and extract the values from it your my-map looks like:
(defn my-map []
[map-view {:style {:flex 1}
:initialRegion {:latitude 52.3702
:longitude 4.89516
:latitudeDelta 0.0922
:longitudeDelta 0.0421}
:onRegionChange (fn [region]
(alert (str "Latitude: "
(goog.object/get region "latitude")
"\nLongitude: "
(goog.object/get region "longitude"))))}])
You can obtain the latitudeDelta and longitudeDelta in the same manner.
When you drag the map the latitude and longitude show up:
The component
If you want access to the component itself your code works fine, you just have to visualize it:
(defn jsx->clj
[x]
(into {} (for [k (.keys js/Object x)] [k (aget x k)])))
(defn my-map []
(let [this (r/current-component)]
[map-view {:style {:flex 1}
:initialRegion {:latitude 37.78825
:longitude -122.4324
:latitudeDelta 0.0922
:longitudeDelta 0.0421}
:onRegionChange (fn [region]
;; Would like to see state here.
(alert "The component..."
(str (jsx->clj this))))}]))
This prints something like:
Not sure if you can do anything with the component, I think you need the Region information.

Clojure web app sql insert only last row when deployed to Tomcat

Good afternoon,
I am using Clojure 1.8, PostgreSQL 9.4 and YeSQL 0.5.2
I have an web app that has a page to insert multiple prices. I get the prices from a HTML Form using Post method. It comes as a map of vector for me. I convert it to a vector of maps so it is easier to manipulate the data. Then I delete previous entries if exists and I do the treatments to the fields and call the DB transaction to insert into the database.
When I use lein ring server it works fine. But when I deploy to Tomcat 9 using lein ring uberwar, the app inserts only the last row.
Here are the my web page:
Each row in the table will be a SQL Insert
My connection:
(ns satus-cotacao.model.connection)
(def db-spec {:classname "org.postgresql.Driver"
:subprotocol "postgresql"
:subname "//localhost/database" ;; 192.168.0.x:port when using other database from the internal network.
:user "root"
:password "root"})
And my defqueries
(ns satus-cotacao.model.cotacao_model
(:require ...
[satus-cotacao.model.connection :refer [db-spec]]
...)
(defqueries "satus_cotacao/model/cotacao.sql"
{:connection db-spec})
The Post request that calls the lcto-cotacao-page using the Form as parameter
POST "/cotacao/:cod" [cod & form :as session] (lcto-cotacao-page cod form session))
The lcto-cotacao-page function to call the Delete and the Insert functions.
(defn lcto-cotacao-page
[cod lcto session]
(try
(cotacao/deleta-lcto-cotacao! cod (:identity session))
(cotacao/insere-lctos-cotacoes! cod (:identity session) lcto)
(layout/render "home.html" {:session session})
(catch Exception e
(do
(timbre/error e)))))
The delete-lcto-cotacao! function and SQL query
(defn deleta-lcto-cotacao!
[codcotacao enti_codigo]
(jdbc/with-db-transaction [tx db-spec]
(delete-lcto-cotacao! {:codcotacao codcotacao
:enti_codigo enti_codigo}
{:connection tx})))
-- name: delete-lcto-cotacao!
DELETE FROM lctocotacao
WHERE lcco_codentidade = :enti_codigo
AND lcco_codcontrole = :codcotacao
The delete works fine, it deletes all entries.
The insere-lctos-cotacoes! to convert from map of vector to vector of maps and create a recursive call through this vector
(defn insere-lctos-cotacoes!
[cod enti lctos]
(if (vector? (:lcco_codprod lctos))
(let [lcto-vec (util/from-map-of-vector-to-vector-of-maps lctos)]
(loop [lcto lcto-vec]
(when (not-empty lcto)
(insere-lcto-cotacao<! cod enti (first lcto))
(recur (rest lcto)))))
(insere-lcto-cotacao<! cod enti lctos)))
Then the function insere lcto-cotacao<! that treats the fields
(defn insere-lcto-cotacao<!
[cod enti lcto]
(let [lcto_codentidade enti
lcto_codcontrole cod
lcto_dtmvto (util/convert-to-data-type (.format (java.text.SimpleDateFormat. "MM/dd/yyyy") (Date.)))
lcto_codprod (Integer. (:lcco_codprod lcto))
lcto_qemb (bigdec (:lcco_qemb lcto))
lcto_qtde (bigdec (:lcco_qtde lcto))
lcto_fpgto (util/empty-field? (:lcco_fpgto lcto) false)
lcto_preco (util/empty-field? (:lcco_preco lcto) true)
lcto_codempresa (util/empty-field? (:lcco_codempresa lcto) false)
new-lcto (assoc lcto :lcco_codentidade lcto_codentidade
:lcco_codcontrole lcto_codcontrole
:lcco_dtmvto lcto_dtmvto
:lcco_codprod lcto_codprod
:lcco_preco lcto_preco
:lcco_qemb lcto_qemb
:lcco_qtde lcto_qtde
:lcco_fpgto lcto_fpgto
:lcco_codempresa lcto_codempresa)]
(insere-lcto-transaction<! (dissoc new-lcto :tpemb :descricao :codbarras :marca))))
And finally the insere-lcto-transaction<! and the SQL query
(defn insere-lcto-transaction<!
[lcto]
(jdbc/with-db-transaction [tx db-spec]
(insert-lcto-cotacao<! lcto {:connection tx})))
-- name: insert-lcto-cotacao<!
INSERT INTO lctocotacao (lcco_codentidade, lcco_codprod, lcco_preco, lcco_dtmvto, lcco_codempresa, lcco_fpgto, lcco_qemb, lcco_qtde, lcco_codcontrole)
VALUES(:lcco_codentidade, :lcco_codprod, :lcco_preco, :lcco_dtmvto, :lcco_codempresa, :lcco_fpgto, :lcco_qemb, :lcco_qtde, :lcco_codcontrole);
Well, thats it. What is strange is that it works fine when I do lein ring server, but when I deploy to lein ring uberwar it doens't work properly.
Also, I tried using Tomcat in Windows and Debian.
Does anyone have an idea why is it happening?
EDIT
After logging, I got some results:
When running local lein ring server
What the POST return into the var form is the same content as the key :param in my session
Also in session, I have the :form-paramsthat has the same content, but instead of using keys like :lcco_fpgto, it uses strings like '"lcco_fpgto"'
{:lcco_fpgto ["001" "001" "001" "001"],
:tpemb ["CX" "CX" "PT" "CX"],
:lcco_qtde ["150.00000" "1.00000" "30.00000" "1.00000"],
:descricao ["Cerveja 350ml Skola" "Adoc 100ml Assugrin Diet" "Cafe 500g Corol Torrado Moido" "Deterg Liq 500ml Alpes Neutro"],
:lcco_codprod ["19" "28" "64" "123"],
:lcco_preco ["1.00000" "2.00000" "3.00000" "4.00000"],
:codbarras ["7896232111149" "7896060010492" "7896184000010" "7896274800124"],
:lcco_codempresa ["001" "001" "001" "001"],
:lcco_qemb ["12.00000" "12.00000" "10.00000" "24.00000"],
:marca ["Skol" "Assugrin" "Corol" "Alpes"],
:__anti-forgery-token ["Unbound: #'ring.middleware.anti-forgery/*anti-forgery-token*" "Unbound: #'ring.middleware.anti-forgery/*anti-forgery-token*" "Unbound: #'ring.middleware.anti-forgery/*anti-forgery-token*" "Unbound: #'ring.middleware.anti-forgery/*anti-forgery-token*"]}
When running the deployed app:
The POST return is the same as the :param key inside session (Only the last element)
{:lcco_fpgto "001",
:tpemb "CX",
:lcco_qtde "1.00000",
:descricao "Deterg Liq 500ml Alpes Neutro",
:lcco_codprod "123",
:lcco_preco "4",
:codbarras "7896274800124",
:lcco_codempresa "001",
:lcco_qemb "24.00000",
:marca "Alpes",
:__anti-forgery-token "Unbound: #'ring.middleware.anti-forgery/*anti-forgery-token*"}
And what I found, is that the :form-params inside my session contains everything, but using strings instead of keys.
:form-params {
"lcco_preco" ["1" "2" "3" "4"],
"tpemb" ["CX" "CX" "PT" "CX"],
"descricao" ["Cerveja 350ml Skola" "Adoc 100ml Assugrin Diet" "Cafe 500g Corol Torrado Moido" "Deterg Liq 500ml Alpes Neutro"],
"lcco_codprod" ["19" "28" "64" "123"],
"lcco_fpgto" ["001" "001" "001" "001"],
"codbarras" ["7896232111149" "7896060010492" "7896184000010" "7896274800124"],
"marca" ["Skol" "Assugrin" "Corol" "Alpes"],
"lcco_qtde" ["150.00000" "1.00000" "30.00000" "1.00000"],
"__anti-forgery-token" ["Unbound: #'ring.middleware.anti-forgery/*anti-forgery-token*" "Unbound: #'ring.middleware.anti-forgery/*anti-forgery-token*" "Unbound: #'ring.middleware.anti-forgery/*anti-forgery-token*" "Unbound: #'ring.middleware.anti-forgery/*anti-forgery-token*"],
"lcco_qemb" ["12.00000" "12.00000" "10.00000" "24.00000"],
"lcco_codempresa" ["001" "001" "001" "001"]}
So, why is that happening? Is it wrong to use the var form that I get in here?
POST "/cotacao/:cod" [cod & form :as session] (lcto-cotacao-page cod form session))
Why is this difference happening?
EDIT 2
My middleware:
https://codeshare.io/mR7Zh

Scala Slick 3: Count Rows and get row

I cannot figure out how to count with Slick (3).
val posts = for {
p <- Posts.query if p.receiver === userId
comments <- Comments.query if comments.postId === p.id
author <- Users.query if p.author === author.id
receiver <- Users.query if p.receiver === receiver.id
} yield (p, comments, author, receiver)
With the following relationships
Posts : Author : Receiver : Comments
1 : 1 : 1 : N
The result should be:
Future[Seq[(Post, User, User, Int)]]
with the int being the count of comments grouped by Posts
Any tips?
You need to group your result by post, author and receiver and the map to aggregate the comments by just counting them.
val posts = (for {
p <- Posts.query if p.receiver === userId
comment <- Comments.query if comments.postId === p.id
author <- Users.query if p.author === author.id
receiver <- Users.query if p.receiver === receiver.id
} yield (p, comment, author, receiver)) //So far thats your current query
.groupBy({ //Group by post, author and receiver
case (post, comment, author, receiver) =>
(post, author, receiver)
})
.map({ //Aggregate your comments (second argument in tuple) and count them
case ((post, author, receiver), list) => {
(post, author, receiver, list.map(_._2).count))
}
})
On mobile currently so this probably won't compile, but you should get the idea.