[[PageOutline]] = GeniusWeb = ''GeniusWeb'' is an open architecture for negotiation via the internet. The core of the architecture is a JSON based communication protocol that standardizes the communication messages comprising a negotiation. This project also contains a java-based reference implementation. It provides protocols, data structures and many components needed in negotiation such as isues, values, domain descriptions, preference profiles, timelines, negotiation protocols, json serialization of these items, automatic negotiation software, etc. This page contains technical documentation describing the core json structures for describing issues, values, bids, offers, negotiation events etc. General info on GeniusWeb, including tutorials, can be found on the [https://ii.tudelft.nl/GeniusWeb/ GeniusWeb main page]. On this page, we take a hands-on, implementation focused approach rather than specifying json structures. The servers (see table below) discuss the structures in more detail. Also for the exact json structures please refer to the examples and the json annotations in the code. == GeniusWeb overview GeniusWeb contains a number of components ||= name =||= description =||= more information =|| ||the core ||the data structures for issues, values, bids, profiles, events and actions, parties etc.||here|| ||profilesserver||a web server that provides profiles and domain descriptions||[https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebProfilesServer profiles server]|| ||partiesserver||A web server that provides instances of running parties to use for negotiation||[https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebPartiesServer parties server]|| ||runserver||A web server that can run sessions and tournaments||[https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebRunServer run server]|| ||stand-alone GUI app||Application that has similar GUI functionality as the servers, but as stand-alone app||[https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebApp gui application]|| You can either run these servers locally on either your computer or on your web server, or use a public server somewhere else. For creating your own profile or party, you only need the core. If you want to get a quick top-down idea how GeniusWeb works, we suggest to install the servers and contact the runserver to run a session. == Installation The GeniusWeb core code does not need to be installed. Check the profilesserver, partiesserver and runserver wiki pages (see above) for installation details. == Server choice, privacy and security You can choose to either run services privately, on your intranet, or completely open on the internet. ||= privacy need =||= configuration =|| ||completely private, no sharing with others ||All services run on tomcat server(s) on your computer or intranet. Outside network access is blocked. You need copies of the profiles and parties (jar files) you want to run.|| ||dedicated business negotiation, competition : share your party with the world, but not its code ||You host your own partiesserver that is connected to the web*. || ||shared profile ||profilesserver on own server or on an existing profilesserver on the web* || ||public party with built-in private profile||Hard-code the profile in the party. Party runs as in competition. || ||semi-private sessions/tournaments||Run your own runserver, possibly even from behind a firewall or on your local computer. Existing parties- and profilesservers are used in your runs. Negotiation results are handled only on your computer and not visible outside. Others might be able to see parties act on your behalf, but it's not trivial to determine that they are negotiating against each other, especially if these parties are on different partiesservers.|| ||run your own protocols||as with running semi-private sessions/tournaments|| * All firewalls above the server have to be configured appropriately, most corporations have firewalls between your computer and inside the company there is only connection between company computers. = Core overview This section gives an overview of the core functionalties. The image below gives an overview class diagram with the GeniusWeb core modules and their functionalities. The figure also shows the 3 servers and the functions inside those. Click on the figure to zoom in. [[Image(source:design/classdiagram.svg, 80%)]] All classes are documented in detail in the javadoc with the code. Also the serialization is annotated with the classes. Here we just give a brief overview. Later in this document we explain the serialization of a domain and profile. Also check the examples to see how this works and what typical values look like. == issuevalue This module contains the basic objects that make up a bid: issues, values, domains, and bids. Javadoc is available on the [http://artifactory.ewi.tudelft.nl/artifactory/webapp/#/artifacts/browse/tree/General/libs-release/geniusweb/issuevalue artifactory]. See [wiki:WikiStart#DownloadingJavaDoc downloading javadoc]. === Issue The issues are just String objects. Issue names must be unique === Value There are two type of values: discrete values and number values. Discrete values are strings eg "low", "yes" or "1". Number values are numbers, eg -1 or 12.423. In GeniusWeb, all number values are processed as BigDecimal to avoid rounding errors. === ValueSet A ValueSet indicates the possible values for an issue. There are 2 types of valuesets: numeric and discrete. DiscreteValueSet contains the list of DiscreteValue which is a basically a possible (string) values for the issue. NumberValueSet contains a Range which is a set of numbers defined by the minimum, maximum and stepsize (upwards from the minimum). * a DiscreteValueSet contains a set of possible discrete values. It looks like "values", a column and then a list of discrete values (all strings) Form example, {{{ "values":["yes","no"] }}}. * a number valueset contains a range of numbers and looks like {{{ {"range":[12.2,12.6,0.3]} }}} so "range:" followed by a list of 3 values. The first value is the minimum value in the range, the second the maximum value in the range, and the third the step value. This example range thus contains 12.2 and 12.5 (the next one would be 12.8 but that is already outside the range). Numbers are without quotes. === Domain A domain is a description of the allowed issues and values for each issue. To avoid confusion in a negotiation, it's important that all participants are dealing with the same domain. A Domain contains a map, with each key the issue (string) and the value a ValueSet. When describing the domain, the set of allowed values has to be given. A domain looks like this {{{ {"name":"jobs", "issuesValues":{ "lease car":{"values":["yes","no"]}, "permanent contract":{"values":["yes","no"]}, "career development opportunities":{"values":["low","medium","high"]}, "fte":{"values":["0.6","0.8","1.0"]}, "salary":{"values":["2000","2500","3000","3500","4000"]}, "work from home":{"values":["0","1","2"]} } } }}} * The name is just a string. Our reference implementation of the profiles server additionally requires that the name must match the filename and directory name when placed on the profiles server. So your directory must be domainsrepo/jobs and the filename must be jobs.json. * The issueValues contains a dictionary with issues. Each issue is indicated by a name (a string), followed by a column (:) and then a ValueSet as discussed above. === Bid Finally, a Bid is a Map where the key is the issue and the value either a DiscreteValue or NumberValue that is valid for that issue. DiscreteValues are serialized to json inside double quotes, NumberValues are just the numbers (no double quotes). Here is an example of a bid in JSON format. issue 2 and issue 3 are number values, issue 1 is a discrete issue. All values in quotes are discrete values, while values without quotes are number values. {{{ {"issuevalues":{ "issue3":9012345678901234567.89, "issue2":1, "issue1":"b" }} }}} Your party can create any bid that it likes but the protocol will check if your bid fits in the current negotiation and may kick you out of the negotiation if you don't behave properly. If you write a java-based party, all these objects may already have been converted to Java objects. Please check [source:issuevalue/src/main/java/geniusweb/issuevalue] for conversion details. There is not yet a domain editor available so you have to create domains by manually editing a file with JSON code. == profile A profile is a function that can tell if a bid is preferred over another bid. Javadoc is available on the [http://artifactory.ewi.tudelft.nl/artifactory/webapp/#/artifacts/browse/tree/General/libs-release/geniusweb/profile artifactory]. See [wiki:WikiStart#DownloadingJavaDoc downloading javadoc]. In the profile module a number of different types of profiles have been defined: * [source:profile/src/main/java/geniusweb/profile/FullOrdering.java FullOrdering]: this provides a function {{{isPreferredOrEqual()}}} that can tell if a bid is preferred over another * [source:profile/src/main/java/geniusweb/profile/PartialOrdering.java PartialOrdering]: as {{{FullyOrderedSpace}}}, but may not know the answer for part of the bids * [source:profile/src/main/java/geniusweb/profile/utilityspace/UtilitySpace.java UtilitySpace]: as {{{FullOrdering}}}, but additionally this provides a function {{{getUtility(bid)}}} that maps the bid into a {{{BigDecimal}}} in [0,1]. The higher the value, the more preferred is that bid. The [source:profile/src/main/java/geniusweb/profile/utilityspace/LinearAdditiveUtilitySpace.java Linear Additive Space] is the most commonly used UtilitySpace. If the accuracy of {{{BigDecimal}}} is not needed, you can just call {{{BigDecimal#doubleValue()}}} to get a standard double. === Linear Additive The most common is the LinearAdditiveUtilitySpace. It contains * the domain description containing the possible issueValues. * the name of the space * the issueUtilities containing a set of ValueSetUtilities. * The issueWeightsL a dictionary assigning a number to each of the issues. These numbers must add up to 1 and determine how much each ValueSetUtility adds to the total utility. * a reservationBid that contains the bid that is the least preferred. Only bids equal or better than this bid should be accepted. To give a full profile example: {{{ {"LinearAdditiveUtilitySpace": {"name":"testprofile", "domain":{"name":"test", "issuesValues":{ "issue2":{"values":["issue2value1","issue2value2"]}, "issue1":{"values": ["issue1value1","issue1value2"]}}}, "issueUtilities":{ "issue2":{"numberutils":{"lowValue":12,"lowUtility":0.3,"highValue":18,"highUtility":0.6}}, "issue1":{"discreteutils":{"valueUtilities":{"issue1value1":0.2,"issue1value2":0.3}}}}, "issueWeights":{"issue2":0.4,"issue1":0.6}, "reservationBid":{"issuevalues":{"issue2":"issue2value1","issue1":"issue1value2"}} }} }}} A party receives a reference to a profile but has to fetch the actual profile. You can defer this task to the ProfileConnectionFactory and in that case you receive a ready-to-use parsed java object. Most likely you get a Linear Additive Utilityspace, please check [source:profile/src/main/java/geniusweb/profile/utilityspace] for conversion details. This is an "LinearAdditiveYtilitySpace", other utilityspaces would have different contents. It contains a number of components: * issueUtilities. Here, each issue value from the domain gets a utility assigned. The two types of issue values each having their matching utility function: ||= Issue Value class =||= Utility class =||= json serialization example =|| {{{#!td DiscreteValue }}} {{{#!td DiscreteValueSetUtilities }}} {{{#!td "discreteutils": { "valueUtilities": { "2000": 0, "2500": 0.25, "3000": 0.3, "3500": 0.75, "4000": 1.0 } } }}} |---------------------------- {{{#!td NumberValue }}} {{{#!td NumberValueSetUtilities }}} {{{#!td numberutils": { "lowValue":12, "lowUtility":0.3, "highValue":18, "highUtility":0.6 } }}} |---------------------------- * issueWeights: this is a map, for each issue there is a value in [0,1] and the sum of the weights in this map must be exactly 1. * domain: identical to above. We replaced some issueValues with "..." in this example . * name: a simple string with the name of the profile. The name must match the filename of the profile. === Partial Ordered In an ordered bidspace, only "isPreferredOrEqual" relationships between bids are known. We use the short notation bid1 >= bid2 to indicate bid1 is preferred or equal to bid2. To test if bid1 and bid2 are exactly equal, you can apply the test bid1 >= bid2 && bid2 >= bid1. In a partial bidspace, only part of the information is available. This means that for some bids you will have neither bid1 >= bid2 nor bid2 >= bid1. Here is a part of a example partial profile for the jobs domain in JSON format: {{{ { "DefaultPartialOrdering": { "name": "jobs1_20", "domain": { "name": "jobs", "issuesValues": { "lease car": { "values": ["yes", "no"] }, ... } }, "better": [ [0, 34], [2, 9], [3, 5], [6, 23],... ], "bids": [{ "issuevalues": { "lease car": "yes", "permanent contract": "yes", "career development opportunities": "low", "fte": "0.8", "salary": "4000", "work from home": "0" } }, { "issuevalues": { "lease car": "no", "permanent contract": "no", ... } }....], "reservationBid": { "issuevalues": { "lease car": "no", "permanent contract": "no", "career development opportunities": "low","fte": "0.6", "salary": "3500", "work from home": "1" } } } } }}} The name, domain and reservationBid fields are as with the LinearAdditiveProfile. * The "bids" field contains a list of the bids that are relevant for this partial profile. Each bid contains (possibly partial) bids in the bid space. * The "better" field contains a list of tuples of numbers. Presence of a tuple (A,B) in this list indicates that bids[A] >= bids[B] where bids[X] means the Xth element in the bids list, 0 being the first element. == Party A party is a program that receives inform messages from the protocol, and can send the actions it wants to take regarding the negotiation back to the protocol. These actions are sent over a websocket that is created by the partiesserver that created the party, which in turn creates this according to a http GET request that comes from a running protocol. The party can also pro-actively search for information and take other actions as it likes, as long as it adheres to the requirements of the protocol (discussed later in this document). Javadoc is available on the [http://artifactory.ewi.tudelft.nl/artifactory/webapp/#/artifacts/browse/tree/General/libs-release/geniusweb/party artifactory]. See [wiki:WikiStart#DownloadingJavaDoc downloading javadoc]. The party module contains the inform objects. There are several, and although they have quite specific meanings, their fine details can be tweaked by the protocol. ||= inform object =||= meaning =|| ||Settings||usually sent as first inform to a party, indicating start of the session and providing the party name, protocol, profile, deadline etc|| ||YourTurn||Indicating that the party receiving this inform now has the turn. || ||ActionDone||Informing that some party did an action|| ||Finished||Indicating that a session has been finished|| Please check the [source:party/src/main/java/geniusweb/party/inform source code of Inform objects] for all the details especially on the json serialization. The party module also contains basic interfaces for implementing your negotiation party. These interfaces are only relevant to create a party compatible with our reference implementation of the [https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebPartiesServer partiesserver]. The main class is Party, which defines the basic functionality required for a negotiation party on our server. The heart of the party is that your Party implements Connectable. Connectable contains 2 main functions: connect and disconnect. When connect is called, your party receives a Connection over which it receives Inform objects and can send Action objects. What exactly is sent and received is determined by the protocol (see the protocol section below). For example if the SAOP protocol is used, your party will receive a YourTurn message, after which it decides on its action and sends it into the Connection. See also the example party discussed below. === Capabilities The party specifies its capabilities. Currently this is a list of behaviours that the party can handle. The 'behaviour' is just a string but it refers to a specific behaviour|| ||= behaviour name =||= abbreviation for =||= expected behaviour =|| || SAOP || stacked alternating offers protocol ||First, this party receives SessionSettings. After that it receives an ActionDone if a party does an action. The party takes an action only after YourTurn is received. It can then either {{{Accept}}}, {{{EndNegotiation}}} or {{{Offer}}}. Accept is possible only after another Offer was received|| || COB || compare bids protocol.||This party receives SessionSettings. It also receives ActionDone if a party does an action, containing a ElicitComparison action if its partner SHAOP party requests so. If it receives that and it receives a YourTurn action after that, The party takes a Comparison action. || || SHAOP || Stacked human alternating offers protocol ||similar to SAOP. A party of this type must receive parameter elicitationcost. If not, the default elicitationcost is 0.1. After receiving a YourTurn action, this party can execute the usual SAOP actions ({{{Accept}}}, {{{EndNegotiation}}} or {{{Offer}}}) or a {{{ElicitComparison}}} action. Each {{{ElicitComparison}}} call will add elicitationcost to the party's spendings. The call results in the associated COB party to execute a Comparison action, whcih is then received inside {{{ActionDone}}}.|| == Timeline The timeline module describes the deadline and a progress objects. Javadoc is available on the [http://artifactory.ewi.tudelft.nl/artifactory/webapp/#/artifacts/browse/tree/General/libs-release/geniusweb/timeline artifactory]. See [wiki:WikiStart#DownloadingJavaDoc downloading javadoc]. The deadline indicates how much time a negotiation session can take and is used to specify the settings for a session or tournament. Two examples: {{{ {"deadlinerounds":{"rounds":100,"durationms":999}} }}} and {{{ {"deadlinetime":{"durationms":2000}} }}} * durationms indicates the maximum run time in milliseconds for the party. The clock starts ticking at the moment the party receives its SessionSettings object. * rounds indicates the maximum number of rounds in the session. The session will end after this number of rounds, deal or no deal. The progress indicates where currently running session is towards the deadline. Progress is contained in the settings object. Round based progress must be updated by the party after each round. == References The references module contains references to remote parties, domains, profiles and protocols that are stored on remote machines. Additionally it contains the interface specifications for connections to remote objects, and some general server objects. Javadoc is available on the [http://artifactory.ewi.tudelft.nl/artifactory/webapp/#/artifacts/browse/tree/General/libs-release/geniusweb/references artifactory]. See [wiki:WikiStart#DownloadingJavaDoc downloading javadoc]. === References We use IRI's (internationalized resource identifier, which looks similar to the well known URLs you use in your web browser) to refer to them. These IRI's are packed inside objects like the PartyRef, ProtocolRef, ProfileRef, DomainRef so that it is clear what type of object the IRI is referring to. For example, when your party is initialized, it usually receives a Settings object that contains a ProfileRef. The intention is that the party fetches the actual profile from the web, using the IRI in the ProtocolRef. See the example party below for an example. There are a number of schemes used for references: ||= scheme =||= used with =||= example =||= comments =|| ||http:||party||http://localhost:8080/partiesserver/run/randompyparty-1.0.0|| || ||ws:||profile||ws://localhost:8080/profilesserver/websocket/get/jobs/jobs1.json|| || ||file:||profile||file:src/test/settings.json ||gives file relative to local current working dir|| ||classpath:||party||classpath:geniusweb.exampleparties.randomparty.RandomParty||must be in classpath|| === Connection The connection objects are used to describe a general connection with a remote Connectable that can respond to requests or take actions pro-actively. The Connection object defines a connection to a Connectable. A ConnectionFactory can create a Connection given a Reference. === serverobjects Here we store objects that are also used in communication with servers. The ServerInfo object contains information about a runserver. Currently it contains the number of free slots and the total number of available slots on the server. == BidSpace The bidspace module contains functionality to support building a negotiation party. Especially for LinearAdditiveSpaces, a number of efficient tools are available that work orders of magnitude faster than brute force algorithms. ||= Class =||= description =|| ||OpponentModel||this is a category of classes that can estimate the opponent's profile from the bids that he places.|| ||Pareto||a category of classes that can compute the pareto frontier from a set of profiles. Pareto optimality is an important mechanism to place optimal bids. ParetoLinearAdditive can efficiently search LinearAdditiveUtilitySpace|| ||AllBidsList||Creates a list containing all possible bids in any domain. Extremely fast; the list is created in a lazy way, and competely avoids storing anything in memory. Can handle sizes that would never fit in memory.|| ||BidsWithUtility||A tool to efficiently search LinearAdditiveUtilitySpace for bids within a certain range.|| Javadoc is available on the [http://artifactory.ewi.tudelft.nl/artifactory/webapp/#/artifacts/browse/tree/General/libs-release/geniusweb/bidspace artifactory]. See [wiki:WikiStart#DownloadingJavaDoc downloading javadoc]. == Protocol The protocol module contains the functionality to define and execute a negotiation protocol. There are session protocols and tournament protocols. The following protocols are available: ||= protocol (abbreviated) =||= full name =||= short description =|| ||SAOP || Stacked Alternating Offers Protocol ||Parties are given turns in a round-robin order. When a party has the turn, it can accept, offer, or end negotiation || ||SHAOP||Stacked Human Alternating Offers Protocol ||Similar to SAOP. Instead of parties, we now have a list of party-pairs [shaop-party","cob-party"]| These pairs run in round-robin order. The shaop-party is the main party that gets the turn. If it does a accept, offer, or end negotiation action, the turn goes to the next shaop-party. If it does an ElicitCompare action, the turn goes to the cob-party who can do a Compare action.|| ||All Permutations||All Permutations||Generates a set of SAOP sessions from a set of parties and profiles.|| Javadoc is available on the [http://artifactory.ewi.tudelft.nl/artifactory/webapp/#/artifacts/browse/tree/General/libs-release/geniusweb/protocol artifactory]. See [wiki:WikiStart#DownloadingJavaDoc downloading javadoc]. The basic classes defining a protocol are: * The [source:/protocol/src/main/java/geniusweb/protocol/NegoSettings.java NegoSettings]: these define the settings for the protocol, such as the deadline, the participants and the profile * The [source:/protocol/src/main/java/geniusweb/protocol/NegoState.java NegoState]: this contains the current state of execution of the protocol. To give some example states: "waiting for bid from party 2", "ended with agreement", "ended because party 1 broke the protocol". A state also has various {{{with()}}} functions defining the new state from an old state and a party doing an action. * The [source:/protocol/src/main/java/geniusweb/protocol/NegoProtocol.java NegoProtocol]: this defines what happens when a negotiation starts, when a participant enters halfway the session, what are the allowed actions, what happens if a participant breaks the protocol, etc. === NegoSettings We discuss two common NegoSettings in more detail, with some examples. Typically the session settings looks like this: {{{ {"SAOPSettings": { "participants":[ {"party":{"partyref":"http://party1","parameters":{}},"profile":"ws://profile1"}, {"party":{"partyref","http://party2","parameters":{}},"profile":"ws://profile2"}], "deadline":{"deadlinetime":{"durationms":100}} }} }}} The "SAOPSettings" indicates that these settings are SAOPSettings and (see Settings.getProtocol) will be interpreted by the SAOP protocol. The participants is a list with PartyWithProfile items: a "party" field containing a http address on a partiesserver, and a "profile" field containing a websocket address on a profilesserver. The deadline contains the deadline for the SAOP, which is how long the negotiation can last. For different protocols, the contents will differ. For a SHAOP configuration, the settings typically look like this {{{ {"SHAOPSettings":{ "participants":[ { "shaop":{"party":{"partyref":"party1","parameters":{}},"profile":"profile1"}, "cob":{"party":{"partyref":"party2","parameters":{}},"profile":"profile1"} }, { "shaop":{"party":{"partyref":"party3","parameters":{}},"profile":"profile1"}, "cob":{"party":{"partyref":"party4","parameters":{}},"profile":"profile1"} } ], "deadline":{"deadlinerounds":{"rounds":30, "durationms":1000}} }} }}} This is similar to SAOP, but instead of just parties we have party tuples "cob","shaop" (see the party behaviours). The party in the "cob" field must follow the cob behaviour, the one with "shaop" a shaop or saop behaviour. The SHAOP party gets the turn first. If it does a normal SAOP action, the turn goes to the next SHAOP party. But if it does a ElicitComparison action, then the turn remains with the SHAOP party (it will not get another YourTurn). The SHAOP party should resume actions when it receives the inform with the Comparison back from the COB party. We strongly recommend using a ROUNDS deadline and a small number of rounds for two reasons * Humans will get tired of comparing bids pretty quickly. There seems no point in using this protocol for large number of comparisons * The log files will become huge if you run this a large, say thousands of rounds, because Comparison are all logged and these are large objects. The run server may even run out of memory on writing log file. The SHAOP protocol can also use parties with the SAOP behaviour. SAOP parties just never call the COB party. The SHAOP protocol still requires you to enter a COB party but this party will never be called. For a tournament, the NegoSettings typically look like this: {{{ {"AllPermutationsSettings":{ "parties":["http://server/../party1","http://server/../party2"], "profiles":["ws://server/../profile1","ws://server/../profile2","ws://server/../profile3"], "reuseParties":false, "partiesPerSession":2, "sessionsettings":{"SAOPSettings":{"participants":[],"deadline":{"deadlinetime":{"millis":10}}}}}} }}} The parties is a list of party URIs, just like in the session settings The profiles is a list of profile URIs, just like in the session settings If reuseParties is set to to false, parties are drawn from the list without return. If it is set to true, parties are drawn with return (meaning all parties can occur multiple times in each session) partiesPerSession sets the number of parties (and matching profiles) for each session. Profiles are always drawn without return (never appear twice in a session) sessionsettings contains basically all the normal run-sessionsettings. This is used as a "template" for all sessions of the tournament. You can put any use any session setting here, and each session will be run according to the protocol you select here. In the example we use the SAOP protocol which takes participants and deadline as arguments, as discussed above. The participants list this time is empty, the AllPermutationsProtocol adds the the required parties to this list. So if you provide a non-empty list here, then these parties would be present in every session in the tournament. If the tournament is used with a SHAOP sessionsettings, a number of rules are used to generate the COB party from the settings * The COB party is assumed to be the {{{comparebids-1.0.0}}} party on the same server as the party you provide. So if you provide {{{http://server/../party1-1.2.3}}} then the cob party will be assumed to be at {{{http://server/../comparebids-1.0.0}}}. * The provided parties that you provide are the SHAOP parties (you can also use SAOP parties). * The provided profile is also given to the SHAOP party. Be aware that you typically need a filter like {{{partial=10}}}. * The COB party gets the profile as specified, but without the query part. * The COB and SHAOP party are thus a fixed pair. = Example Parties Example parties can be found [source:/exampleparties here]. Many of these are also included with the basic [https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebPartiesServer parties server] to provide basic functionality. == HumanGUI party The HumanGUI party is a party that shows a GUI to allow the user to manually interact with a negotiation. This GUI is shown on the machine where the partiesserver is running. This is also the reason that this party is not included with the default partiesserver. If you want to use this you need to download the latest version of the jar file from [http://artifactory.ewi.tudelft.nl/artifactory/webapp/#/artifacts/browse/tree/General/libs-release/geniusweb/exampleparties/humangui the artifactory] and install it on your partiesserver. = Writing a party in Java Example parties can be found [source:/exampleparties here]. You can easily clone a party with SVN using {{{svn co https://tracinsy.ewi.tudelft.nl/pub/svn/GeniusWeb/exampleparties/randomparty/}}} (this clones randomparty, use a different name to fetch another example). A party is compiled with maven. After compilation ({{{mvn package}}}) you get a {{{target/yourparty-X.Y.Z-jar-with-dependencies.jar}}} that can be copied into the parties server for deployment. The basic structure of an party looks like this {{{ public class RandomParty extends DefaultParty { @Override public void notifyChange(Inform info) { if (info instanceof Settings) { Settings settings = (Settings) info; this.profileint = ProfileConnectionFactory .create(settings.getProfile().getURI(), getReporter()); this.me = settings.getID(); this.progress = settings.getProgress(); } else if (info instanceof ActionDone) { Action otheract = ((ActionDone) info).getAction(); if (otheract instanceof Offer) { lastReceivedBid = ((Offer) otheract).getBid(); } } else if (info instanceof YourTurn) { myTurn(); if (progress instanceof ProgressRounds) { progress = ((ProgressRounds) progress).advance(); } } else if (info instanceof Finished) { getReporter().log(Level.INFO, "Final ourcome:" + info); } } private void myTurn() { Action action; if (isGood(lastReceivedBid)) { action = new Accept(me, lastReceivedBid); } else { // for demo. Obviously full bids have higher util in general AllPartialBidsList bidspace = new AllPartialBidsList( profileint.getProfile().getDomain()); Bid bid = null; for (int attempt = 0; attempt < 20 && !isGood(bid); attempt++) { long i = random.nextInt(bidspace.size().intValue()); bid = bidspace.get(BigInteger.valueOf(i)); } action = new Offer(me, bid); } getConnection().send(action); } private boolean isGood(Bid bid) { return bid != null && ((LinearAdditiveUtilitySpace) profileint.getProfile()) .getUtility(bid).doubleValue() > 0.6; } @Override public Capabilities getCapabilities() { return new Capabilities(new HashSet<>(Arrays.asList("SAOP"))); } @Override public String getDescription() { return "places random bids until it can accept an offer with utility >0.6"; } } }}} The party must follow the behaviours that it promises. The example above folows the SAOP behaviour but other examples like comparebids and simpleshaop are available as example. == Preparing the jar file In order to put your party on the [https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebPartiesServer partiesserver] for running, you need a jar file of your party. Normally the party includes all dependencies. The jar files are loaded with an isolated jar class loader that should avoid collisions with possibly identically named but possibly different packages in other jar files. Party jar files must have a Main-Class set in the MANIFEST.MF file. This main-class must implement Party and have a no-arg constructor. The example randomparty does this from the maven build script. We recommend to do initialization of the party only in the init() and not in the constructor or static code. This because instances of your class can be made both for extracting general info as getDescription(), or to really run your class. = Writing a party in Python We provide a python-to-java adapter so that you can easily write your party in python instead of Java. You can check the full working example code [source:/exampleparties/randompartypy/src/main/resources/RandomParty.py here]. A python-based party looks like this: {{{ class RandomParty (DefaultParty): def notifyChange(self, info): if isinstance(info, Settings) : self.profile = ProfileConnectionFactory.create(info.getProfile().getURI(), self.getReporter()); self.me = info.getID() self.progress = info.getProgress() elif isinstance(info , ActionDone): self.lastActor = info.getAction().getActor() otheract = info.getAction() if isinstance(otheract, Offer): self.lastReceivedBid = otheract.getBid() elif isinstance(info , YourTurn): self._myTurn() if isinstance(self.progress, ProgressRounds) : self.progress = self.progress.advance(); def getCapabilities(self): # -> Capabilities return Capabilities(HashSet([ "SAOP"])) def getDescription(self): return "places random bids until it can accept an offer with utility >0.6. Python version" def terminate(self): self.profile.disconnect() def _myTurn(self): if self.lastReceivedBid != None and self.profile.getProfile().getUtility(self.lastReceivedBid).doubleValue() > 0.6: action = Accept(self.me, self.lastReceivedBid) else: bidspace = AllPartialBidsList(self.profile.getProfile().getDomain()) bid = None for attempt in range(20): i = self.random.nextInt(bidspace.size()) # warning: jython implicitly converts BigInteger to long. bid = bidspace.get(BigInteger.valueOf(i)) if self._isGood(bid): break action = Offer(self.me, bid); self.getConnection().send(action) def _isGood(self, bid): return bid != None and self.profile.getProfile().getUtility(bid).doubleValue() > 0.6; }}} The python party must be wrapped into a jar wrapper to get it accepted by the parties server. This is done automatically by the maven build script, again just execute {{{mvn package}}} to build. The javadoc with the [source:/pythonadapter/src/main/java/geniusweb/pythonadapter/PythonPartyAdapter.java PythonPartyAdapter] gives the details about this wrapper. = Writing a party in other languages If you want to use another language than java or python2 to write your parties, you have a number of options * Make your own adapter that runs your language from Java. Check [source:pythonadapter/src/main/java/geniusweb/pythonadapter/PythonPartyAdapter.java our pythonadapter] for an example how this can be done. * Write your own partiesserver that correctly implements the [https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebPartiesServer partiesserver interface]. This boils down to creating a webserver that correctly can handle calls to a number of prescribed URLs and websockets. = Stand-alone Running = For stand-alone running you need to have the following available in your project space (this includes the maven dependencies you have set for your project) * The parties you want to run (in compiled form) must be in your classpath * The profiles you want to provide to the parties (alternatively you can refer to a profile on a running profile server) * A settings.json file containing the [source:/protocol/src/main/java/geniusweb/protocol/session SessionSettings] eg SAOP Settings. [source:/simplerunner/src/test/resources/settings.json view example file]. * a simple stand-alone runner, eg download from [http://artifactory.ewi.tudelft.nl/artifactory/libs-release/geniusweb/simplerunner/ geniusweb artifactory] select latest version simplerunner--jar-with-dependencies.jar. A complete example is available of [source:/simplerunner simplerunner here] == Running == Make sure your parties are in the java classpath. A stand-alone runner can now be started as follows (using the example, set your working directory to the root of the simplerunner project ) {{{ java -jar simplerunner...with-dependencies.jar src/test/resources/settings.json }}} When the protocol is completed, the runner prints out the final state which usually contains all actions that were done as well. = Debugging = Debugging can be done in several ways * From Eclipse EE: * Place your party source code in the Eclipse workspace * Place a breakpoint in your party's code * Run the partiesserver directly from Eclipse EE , in Debug mode. * Run a session or tournament in which you want to debug your party. * Eclipse will halt server execution and switch to debugging when it hits your breakpoint * Be aware of the automatic time-outs that will still be enforced while you are debugging. This includes tomcat session time-outs. * Using a stand-alone runner (normal Eclipse for Java developers, no EE needed) * Have your party's source code in the Eclipse workspace * Clone the simplerunner into your workspace {{{svn co https://tracinsy.ewi.tudelft.nl/pub/svn/GeniusWeb/simplerunner}}} * Edit the src/test/resource/settings.json file in the simplerunner to match your party * Place a breakpoint in your party where you want to debug. * Create a debug configuration for NegoRunner with some customized settings: * Add your party to the user entries in the classpath. * Set {{{src/test/resources/settings.json}}} as program argument * Run the debug configuration * Eclipse will halt server execution and switch to debugging when it hits your breakpoint * time-outs may still be enforced while you are debugging but you avoid the Tomcat session time-out. * With stand-alone runner, your parties are run together in a single classloader. This is different from running in the partiesserver. = GeniusWeb sources = == downloading source code You can browse the GeniusWeb core sources directly using the browse button at the right top of this page. You can download the source code of this component using {{{svn co https://tracinsy.ewi.tudelft.nl/pub/svn/GeniusWeb/}}} Normal developers that write new parties do not need to install the GeniusWeb source code. Even if you want to debug/trace into the GeniusWeb code -- for instance for debugging or understanding the inner workings of geniusWeb--, IDEs like Eclipse automatically allow this as they download the source codes automatically from the maven artifactory. == Import all sources in Eclipse Install Subclipse using "help/Eclipse MarketPlace" and search for subclipse. Disable the JavaHL native DLLs and install. NOTE: due to a bug in Eclipse Photon the marketplace may not work. We suggest to upgrade... You may get some errors on JavaHL library. To get rid of those, go to preferences/Team/SVN/ * disable General SVN settings / JavaHL * SVN interface/Client: select SVNKit instead of JavaHL. Right click in Package Explorer in Eclipse, select "Import/SVN/Checkout Projects from SVN". Select the root of the project, finish (selecting sub-projects will result in a stupid loop in the checkout procedure in Eclipse and won't lead anywhere...) Richt click on the checked-out project that you want eclipse to recognise as Maven project (the project are maven but Eclipse does not recognise this after check-out). Select import/maven/existing maven projects. Finish. Note. Eclipse does not automatically recognise this as a maven project because Eclipse supports this only with GIT repositories while we use SVN. == Downloading JavaDoc IDE's like Eclipse download the javadocs automatically. But it is also possible to download them manually and browse them with a web browser. All modules are availabel on the [http://artifactory.ewi.tudelft.nl/artifactory/webapp/#/artifacts/browse/tree/General/libs-release/geniusweb artifactory] ( you need to have cookies enabled). * Go to the artifactory * Select the module you need javadoc for * Select the correct (usually the latest) version of the module * download the {{{*.javadoc.jar}}} (right-click on the jar) * unzip it, eg using your favourite archive manager or with {{{jar xf}}}. Don't double click it * open the index.html [[Image(https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWeb/raw-attachment/wiki/WikiStart/downloadjavadoc.png)]] Figure. Manually downloading the javadoc from the artifactory