Global visibility of another person in Inform7? - inform7

In a segment of a project I am working on for college, it is asked that one is able to steer another person using a kind of a walkie-talkie. However this requires some kind of global access to the person one should be able to control like that. One could probably do one of the following:
Swap the player each time he asks the other character to do something, carry out the action and return
Using the walkie talkie to change the views of the character (which does not look like an intuitive way of playing to me)
Somehow make the other character visible in every room (which would be the one I would prefer the most)
Unfortunately I was unable to find anything like that in the documentation (visibility is only lighting in one room, reachability only opening/taking something out of something). Another way I thought of was saving the origin room of both, place them in one secret room, c1 then asks c2 to try doing something, both are placed to their positions, and the action asked for is carried out by c2.
However writing this as a before rules does not work, because it is already cancelled by the default check rule. On the other hand I cannot write:
Check asking c2to try doing something
because that is to general.
Any ideas, approaches or solutions are welcome!

The concept you're looking for is "scope" (Writing with Inform ch. 18.29.) The following places "c2" in scope and therefore makes it accessible everywhere:
After deciding the scope of the player:
place c2 in scope.
You can also make it conditional:
After deciding the scope of the player when the player is carrying the walkie talkie:
place c2 in scope.
The rest is fine tuning. The following prevents commands that aren't logical when c2 isn't physically in the same space (like "look at c2"):
Before doing something to c2 when c2 is not in the location and not answering c2 that:
say "C2 isn't here right now. You can tell it what to do through the walkie talkie by commanding for example C2, JUMP." instead.
This one prevents the "You can't reach into..." error when the issued command is invalid:
Before answering c2 that:
say "C2 doesn't understand that command." instead.

Related

How to handle required relationships in Firebase Realtime Database?

Local SQL
Locally in my application I have data models Foo and Bar, each stored in a separate SQL table.
Foo references Bar by its id, and it would be an error to have a Foo without its counterpart: Bar.
Sometimes they are shown together, other times only one is shown at a time, and its possible to edit one without it affecting the other.
Firebase Realtime Database
I am now investigating how I can best integrate it into my application to ensure a smooth sync & backup experience. Everything is pretty much straight forward; but I cannot wrap my head around how I can ensure that the above mentioned contract stays true.
There will be cases where Foo is synchronized; and Bar is only synchronized sometime later (consider a simple drop of network connectivity). During this period of time, the realtime database for this particular user would be considered to be in an illegal state. When connectivity returns, both Foo and Bar will eventually be synchronized and the entire thing can continue flowing - but what do I do until then? How can I safeguard against it? Do I need to, or am I looking for the answers in all the wrong places?
Some ideas that Ive been exploring:
Allow Bar to be missing locally. Consider Foo to be in a partial state whenever its bar is missing, e.g. it could be hidden in the UI until its "ready".
Somehow combine Foo and Bar locally, only save Foo when its Bar is available, etc.
Nest Bar inside Foo such that theyre always synchronized together. (This seems troublesome, I have a couple of relationships like Foo->Bar in my application and I would have to nest Bar inside all of them if this was the 'correct' way of handling it)
Please enlighten me if you can. Firebase isnt new to me, but synchronizing this kind of complex data with a multitude of relationships, is.
Additional context
While I cant share the actual Foo & Bar, I have an example which I believe resembles the challenge well.
Consider a chat application where there are messages, rooms and users.
You can post a message to a room, and you can edit a room name and color. A message cannot exist without a user and a room. When looking at it from a sync perspective, user, room and message now has to be synchronized "together" (or at the very least, a message would be invalid if it came through without the others).
Handling this with multi-path updates I would update all 3 everytime a message is posted/edited. Have I understood this correctly? If so, that would mean updating 1+N+N nodes in my own scenario. The N+N nodes wouldnt have any actual updated data, but would be included in the update to ensure all of it is synchronized together.
Further clarity
First, going back to the root of the problem - Foo references Bar by its id locally. If my application ends up in a state where either exist without the other, it would cause issues pretty much everywhere (this is what Im referring to as an illegal state, it cannot happen).
Considering ways to safeguard against it, Ive been recommended to use a multi-path update in firebase (I believe this is similar/identical to fan-out?). Ill try this approach shortly even though Im feeling reserved about it, just to verify whether what Im feeling is just from inexperience.
Im having a very hard time wrapping my head around the fact that if Foo changes locally, it would now also result in a query happening for Bar, such that both can be synchronized together to firebase. It sounds OK for such a simple scenario, however in practice it would mean something along the lines of: you make an edit to X and it gets saved locally, shortly thereafter a sync is happening to firebase, now 100:s of Y and Z are queried as well, and inserted into firebase in the same operation. Y & Z are likely already up to date in firebase at this point, and they havent changed locally.
I dont have much experience with these kinds of scenarios when it comes to firebase, my thinking goes along the lines of it being a huge waste of resources - Im sure firebase does a lot of work locally such that unnecessary synchronization work wont happen for data that hasnt actually changed, but I cant escape the thought that I would still be querying for 100:s and 100:s of complex models locally a lot, in cases where it doesnt seem necessary (surely another approach must exist where I tackle the problem from another angle?).
There will be cases where Foo is synchronized; and Bar is only synchronized sometime later (consider a simple drop of network connectivity).
If both writes come from the same client, consider using multi-path updates to prevent such partial updates.
I finally managed to solve this, hopefully this can help someone else out there that runs into the same challenge further down the line!
First and foremost, when registering ChildEventListener on a DatabaseReference; I get one notification with the latest version of the data, and then notifications each time the data changes.
Using that, I filter data by its "version" (basically a timestamp of when it was edited) so that only data that is newer than the latest local version of it is actually processed.
Anytime a Foo comes through and its Bar counterpart hasnt arrived yet, Ill mark it as a deferred-task that should be retried after the next sync operation is complete - in almost all cases, Bar will come through after Foo and the task will succeed on its next retry. In some cases a couple of other sync operations will come through before Bar, but my retry logic is all local and cheap, so I dont mind that.
If no Bar shows up during this lifetime of the application, its not a problem as the latest version of Foo will come through the next time the application is started, and the cycle just repeats itself until both Foo & Bar are available, at which point theyre inserted into my local database.
I dont know if this is the "correct" way to solve it. But using my knowledge, it is the best I could come up with that works, and I dont see any real downsides to it. Feel free to criticize it in the comments, or provide another answer if you think you have a better solution!
Thank you.

How To Exclude Certain Relationship for Real-Time Prediction in Neo4j

So I'm working on a real-time prediction matter, for example, I have a node (A) (:Person) and he has friends and node (B) as (:Games)
so node (A) has liked a certain Game and his friends liked other games so I recommend those other games for him But the matter is that I need to exclude the games which he is already liked or played.
it seems to be easy around the 'NOT' command but I couldn't find the right code for it yet although I've tried a lot of ways
the one seems closest for me is like:
match (A:Person)-[:Friend]-(n:Person)
where A <> n
with distinct n
match (n)-[:LIKED]-(B:Game)-[:ON]-(:steam), (k:Person{name:'John'})
where not ((k)-[:LIKED]-(:Game)-[:ON]-(:steam))
return B
which has to recommend the games John's friends liked without the games which John already liked.
anyway, when I Run this, the Graph just freezes for a while and then shutdown which is another problem I want to ask for.
Thanks for help
The last WHERE clause has very few constraints on it, and probably explains the hang/timeout. It may help to have a variable name for each label, either to constrain the query or to receive the nodes. more like this
where not ((k:Person{name:'John'})-[:LIKED]->(B:Game)-[:ON]->(C:steam))
return B
specify directional -> relationships (as above) in cypher queries if possible, usually it provides the answer you want, and is faster.
adding the variable name, and relationship direction also makes the query easier to read, to understand what it is doing, and if you need to look at the nodes/relationships values when debugging.
I may be wrong, but the :steam label doesn't look right to me. What are example values? I'm wondering if you meant to have a :service node, and steam would be a node instance?
Note: if you provide create nodes/rels script to create a small example of this database (e.g. a dozen nodes with these relationships) it would be easier to provide a working cypher example.
If you want to find the distinct games on Steam that John's friends liked but John has not yet liked or played, something this should work:
MATCH (j:Person{name:'John'})-[:FRIEND]-(:Person)-[:LIKED]->(g:Game)-[:ON]-(:steam)
WHERE NOT (j)-[:LIKED|PLAYED]->(g)
RETURN DISTINCT g

how to use zz mutually defined BIG07 - Liaison EDI notepad

note: I am using Liaison EDI notepad for syntax error checking.
For EDI processing there are a lot of places where you can use 'ZZ=mutually defined' as a value. For instance, I am working with creating an 810 4010 document, and for BIG07 (transaction type code) none of the codes that I can choose are the ones I want. I want my customers to use codes that I create. I want them to use the code 'HR' for human resource or 'SC' for supply chain. So can someone tell me how I can do this? And also what does 'ZZ=mutually defined' in Liaison EDI notepad mean?
First, make sure you want and need to do this. "Human Resource" and "Supply Chain" don't really sound like credible invoice types and you risk just annoying the trading partners with such a deviation. There are several hundred valid codes already.
How exactly do you plan to use this? Maybe there is a better way, like the NTE segment which kind of a catch-all already.
ZZ is not a Liaison specific qualifer. ZZ means mutually defined per the ANSI X12 standard. It's kind of a "catch all" where the trading partners can agree that ZZ will suit their needs because the other codes might not necessarily apply. It's used a lot of times in the ISA where a trading partner will arbitrarily make up their identifier instead of using a phone number or DUNS number.
Besides Google, there are a few resources out there like give you a high level of how EDI works. I'm assuming BizTalk doesn't provide you with a solid X12 dictionary viewer, so perhaps you might want to purchase the Dictionary Viewer from Liaison. You might want to check out http://www.edibasics.com/
You need to check with your customers to see if they can even provide what you're looking for. If not, you're just wasting your time. If you're going to bastardize the standard (which is not uncommon) it doesn't mean your partner is going to jump through the hoops to give you what you want. It might not be feasible on their end, and you could wind up irritating your customer. Irritating a customer is never a good idea. On their end, it is possible that an invoice is an invoice and they can't differentiate between the two. Or, they might be able to differentiate by an invoice number prefix or suffix. Then your mapping logic can use that.

'If' arguments involving the player in Inform 7 causing contradictions

I'm trying to make a game in Inform 7 and have encountered a major problem, the answer to which apparently can't be found with a google search.
I'm using an 'if' argument to change certain situations based on what room the player is in. Instead of seeing what I have written as an 'if' argument, it has assumed 'If the player' to be an entity of itself.
This is the error message:
You wrote 'If the player is in Reception' , but also 'If the player is in
the Corner Table' : that seems to be saying that the same object (If
the player) must be in two different places (Reception and Corner
Table). This looks like a contradiction.
This is my code in both places:
If the player is in the Corner Table;
Understand the command "leave" or "exit" as something new.
Understand "leave" or "exit" as northwest.
If the player is in Reception;
Understand "key" as the Janitor's Key.
So, uh... can anybody help me?
There are several issues with the code you posted:
You can't have an if phrase out of context. You must write a rule for when the if phrase is considered.
Conversely, you can't use understand phrases in context. More specifically, if ...: understand "..." as ... isn't possible. Understand phrases must always be standalone.
The if phrases should end in a colon, not a semicolon.
"northwest" by itself is not an action; "going northwest" is.
You apparently want this instead:
Instead of exiting when the location is the Corner Table:
try going northwest.
This redirects the exiting action (which includes the commands "leave" and "exit") to the going northwest action in that particular room.
For the second if phrase, firstly if you have an object called "Janitor's Key" the game already understands "key" as referring to this object unless you've specifically made the object privately-named. Secondly, why have the game recognize "key" only in one location? Built-in scoping already makes sure that you can't refer to things that are not in the same room as the player.
So if the object is privately-named, and there's a reason why the key should be referred as such only in one location, the code for that is:
Understand "key" as the Janitor's Key when the location is the Reception.
But, as said, this is necessary only in very specific situations and most likely it's best to let the standard library handle it and leave it out altogether.

Is there (or has there been considered) anything like 'merge' or 'batch' setting in Firebase?

In doing a bit more programming with Firebase today, I found myself wishing for a couple of features:
1) Merge set:
Say I have a firebase ref that has the value {a:1,b:2,c:3}.
If I do something like ref.set({a:-1,b:-2}) the new value will (unsurprisingly) be {a:-1,b:-2}.
Instead, imagine ref.mergeSet({a:-1,b:-2}) which would have a result in the value of the ref being {a:-1,b:-2,c:3}.
Now, I realize that I could do something like ref.child("a").set(-1) and ref.child("b").set(-2) to achieve this result, but in at least some cases, I'd prefer to get only a single call to my .on() handler.
This segues into my second idea.
2) Batch set:
In my application I'd like a way to force an arbitrary number of calls to .set to only result in one call to .on in other clients. Something like:
ref.startBatch()
ref.child("a").set(1)
ref.child("b").set(2)
....
ref.endBatch()
In batch mode, .set wouldn't result in a call to .on, instead, the minimal number of calls to .on would all result from calling .endBatch.
I readily admit that these ideas are pretty nascent, and I wouldn't be surprised if they conflict with existing architectural features of Firebase, but I thought I'd share them anyway. I find that I'm having to spend more time ensuring consistency across clients when using Firebase than I expected to.
Thanks again, and keep up the great work.
UPDATE: We've added a new update() method to the Firebase web client and PATCH support to the REST API, which allow you to atomically modify multiple siblings at a particular location, while leaving the other siblings unmodified. This is what you described as "mergeSet" and can be used as follows:
ref.update({a: -1, b: -2});
which will update 'a' and 'b', but leave 'c' unmodified.
OLD ANSWER
Thanks for the detailed feature request! We'd love to hear more about your use case and how these primitives would help you. If you're willing to share more details, email support#firebase.com and we can dig into your scenario.
To answer your question though, the primary reason we don't have these features is related our architecture and the performance / consistency guarantees that we're trying to maintain. Not to go too deep, but if you imagine that your Firebase data is spread across many servers, it's easier for us to have stronger guarantees (atomicity, ordering, etc.) when modifying data that's close in the tree than when modifying data that's far away. So by limiting these guarantees to data that you can replace with a single set() call, we push you in a direction that will perform well with the Firebase architecture.
In some cases, you may be able to get roughly what you want by just reorganizing your tree. For instance, if you know you always want to set 'a' and 'b' together, you could put them under a common 'ab' parent and do ref.child('ab').set({a:-1, b:-2});, which won't affect the 'c' child.
Like I said, we'd love to hear more about your scenario. We're in beta so that we can learn from developers about how they're using the API and where it's falling short! support#firebase.com :-)

Resources