Commit 6adf57fd authored by Tom Gordon's avatar Tom Gordon

Added a means to delete cases, as yet without confirmation

parent 3b827165
......@@ -5,6 +5,9 @@
// at http://mozilla.org/MPL/2.0/.
// Models of the dimensions and similarity of cases in some domain
// See https://en.wikipedia.org/wiki/Multidimensional_scaling
// for ideas about how to visualize similarity measures
package domain
import (
......@@ -92,10 +95,11 @@ func (m *DomainModel) IsPosition(sid string) bool {
// Case similarity is measured using the geometric mean of the ordinal
// distance between the factors of the dimensions
func (m *DomainModel) Similarity(c1 Case, c2 Case) float64 {
func (m *DomainModel) GeometricMeanSimilarity(c1 Case, c2 Case) float64 {
if !m.initialized {
m.init()
}
deltas := []float64{}
for k, d := range m.Dimensions {
f1, ok1 := c1[k]
......@@ -116,7 +120,48 @@ func (m *DomainModel) Similarity(c1 Case, c2 Case) float64 {
// add 1 to the differences to avoid multiplying by zero
product = product * (delta + 1)
}
n := len(deltas)
mean := math.Pow(product, 1.0/float64(n))
return 1.0 / mean
}
func (m *DomainModel) ArithmetricMeanSimilarity(c1 Case, c2 Case) float64 {
if !m.initialized {
m.init()
}
// deltas is a list of the differences of the *normalized* factors of
// each dimension
deltas := []float64{}
normalize := func(f string, d *Dimension) float64 {
n := float64(len(d.Factors))
i := d.rank[f]
return (i * float64(100)) / n
}
for k, d := range m.Dimensions {
f1, ok1 := c1[k]
if !ok1 {
f1 = d.Default
}
f2, ok2 := c2[k]
if !ok2 {
f2 = d.Default
}
deltas = append(deltas, math.Abs(normalize(f1, d)-normalize(f2, d)))
}
// compute the arithmetric mean of the deltas
var sum float64 = 0.0
for _, delta := range deltas {
sum = sum + delta
}
n := len(deltas)
return 1.0 / math.Pow(product, 1.0/float64(n))
mean := sum / float64(n)
return (100.0 - mean) / 100.0
}
// Copyright © 2015 Thomas F. Gordon
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL
// was not distributed with this file, You can obtain one
// at http://mozilla.org/MPL/2.0/.
package web
import (
"encoding/json"
"html/template"
"io/ioutil"
"net/http"
"path"
)
func makeDeleteCaseHandler(couchdbURL string, dbName string, errorTemplate *template.Template, templatesDir string) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, req *http.Request) {
caseId := path.Base(req.URL.Path)
url := couchdbURL + dbName + "/" + caseId
resp, err := http.Get(url)
if err != nil {
errorTemplate.Execute(w, err.Error())
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
errorTemplate.Execute(w, err.Error())
return
}
data := make(map[string]interface{})
err = json.Unmarshal(body, &data)
rev := data["_rev"]
req2, err := http.NewRequest("DELETE", couchdbURL+dbName+"/"+caseId+"?rev="+rev.(string), nil)
if err != nil {
errorTemplate.Execute(w, err.Error())
return
}
client := http.Client{}
resp, err = client.Do(req2)
if err != nil {
errorTemplate.Execute(w, err.Error())
return
}
defer resp.Body.Close()
home := &templateHandler{filename: "argumentation-tool.html", templatesDir: templatesDir}
home.ServeHTTP(w, nil)
}
}
......@@ -27,9 +27,11 @@ type SimilarCase struct {
// to satisfy the sorting interface
type BySimilarity []SimilarCase
func (a BySimilarity) Len() int { return len(a) }
func (a BySimilarity) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a BySimilarity) Less(i, j int) bool { return a[i].Similarity >= a[j].Similarity }
func (a BySimilarity) Len() int { return len(a) }
func (a BySimilarity) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a BySimilarity) Less(i, j int) bool {
return a[i].Similarity >= a[j].Similarity
}
func makeSearchHandler(couchdbURL string, dbName string, errorTemplate *template.Template, templatesDir string) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, req *http.Request) {
......@@ -117,7 +119,7 @@ func makeSearchHandler(couchdbURL string, dbName string, errorTemplate *template
// Compare the similarity of the precedent to the current
// case and record the result in the case table
if decision != "" {
v := model.Similarity(currentCase, precedent)
v := model.ArithmetricMeanSimilarity(currentCase, precedent)
sc := SimilarCase{
Id: c.Id,
Title: c.Value.Title,
......
......@@ -15,10 +15,12 @@
<h1>EAGLE Argumentation Tool</h1>
</div>
<div role="main" class="ui-content">
<ul data-role="listview" data-inset="true">
<li><a href="/new-case-form">Enter a new case</a></li>
<li><a href="/search-cases-form">Search for similar cases</a></li>
</ul>
</div>
<div data-role="footer" data-id="main-footer" data-position="fixed">
<div data-role="navbar">
......
......@@ -63,6 +63,7 @@
<fieldset data-role="controlgroup" data-type="horizontal">
<input type="submit" value="Find Similar Cases"/>
<a href="/map-case/{{.Id}}" target="_self" class="ui-btn">Argument Map</a>
<a href="/delete-case/{{.Id}}" target="_self" class="ui-btn">Delete Case</a>
</fieldset>
</form>
......
......@@ -15,9 +15,11 @@
<h1>Error Message</h1>
</div>
<div role="main" class="ui-content">
<p>
{{.}}
</p>
</div>
<div data-role="footer" data-id="main-footer" data-position="fixed">
<div data-role="navbar">
......
......@@ -17,8 +17,8 @@
</div>
<div role="main" class="ui-content">
<p>To be written.</p>
</div>
<div data-role="footer" data-id="main-footer" data-position="fixed">
<div data-role="navbar">
......
......@@ -85,7 +85,7 @@ Germany</p>
<p>We cannot assume any liability for the content of external pages. Solely the operators of those linked pages are responsible for their content.
We make every reasonable effort to ensure that the content of this Web site is kept up to date, and that it is accurate and complete. Nevertheless, the possibility of errors cannot be entirely ruled out. We do not give any warranty in respect of the timeliness, accuracy or completeness of material published on this Web site, and disclaim all liability for (material or non-material) loss or damage incurred by third parties arising from the use of content obtained from the Web site.
Registered trademarks and proprietary names, and copyrighted text and images, are not generally indicated as such on our Web pages. But the absence of such indications in no way implies that these names, images or text belong to the public domain in the context of trademark or copyright law.</p>
</div>
<div data-role="footer" data-id="main-footer" data-position="fixed">
<div data-role="navbar">
......
......@@ -15,6 +15,7 @@
<h1>New Case Successfully Created!</h1>
</div>
<div role="main" class="ui-content">
<h2>Actions</h2>
<fieldset data-role="controlgroup" data-type="horizontal">
......@@ -22,6 +23,7 @@
<a target="_self" href="/map-case/{{.}}" class="ui-btn">Argument Map</a>
<a href="/" class="ui-btn" data-icon="home">Home</a>
</fieldset>
</div>
<div data-role="footer" data-id="main-footer" data-position="fixed">
<div data-role="navbar">
......
......@@ -16,10 +16,11 @@
<h1>Similar Cases Found</h1>
</div>
<div role="main" class="ui-content">
<p>The most similar cases for each position are listed, in order of similarity,
showing the most similar cases first.</p>
<div role="main" class="ui-content">
{{range $position, $cases := .}}
<h3>{{$position}}</h3>
{{if $cases}}
......
......@@ -46,6 +46,8 @@ func ArgumentationToolServer(httpPort string, couchdbURL string, dbName string,
http.HandleFunc("/view-case/", viewCaseHandler)
mapCaseHandler := makeMapCaseHandler(couchdbURL, dbName, errorTemplate, templatesDir)
http.HandleFunc("/map-case/", mapCaseHandler)
deleteCaseHandler := makeDeleteCaseHandler(couchdbURL, dbName, errorTemplate, templatesDir)
http.HandleFunc("/delete-case/", deleteCaseHandler)
// start the web server
if err := http.ListenAndServe(":"+httpPort, nil); err != nil {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment